[Перевод] Selenium WebDriver – Метрика тестов в реальном времени с использованием Grafana и InfluxDB
Всем привет! Уже на следующей неделе стартуют занятия в группе «Java QA Engineer». Этому и будет приурочена нынешняя публикация.
Обзор:
Ежедневное выполнение автоматизированных регрессионных тестов в рамках каждодневной сборки неизбежно на настоящий момент. Приятно находить и сообщать об ошибках, сразу после их нахождения. Одновременно с этим проблематично проводить сотни автоматизированных тестов и удаленное параллельное выполнение. Как только у вас появляется набор автоматизированных регрессионных тестов, вы можете разбить его на несколько наборов по бизнес-модулям и запускать их параллельно, как часть ежедневного автоматизированного регрессионного тестирования. Большинство таких тестовых наборов выполняются на удаленной виртуальной машине, а результаты теста становятся доступны только после его выполнения. В противном случае, вы можете заглянуть в консоль jenkins, чтобы увидеть логи процесса выполнения теста. Иногда это раздражает. Было бы здорово иметь приложение, которое выдавало бы информацию о прохождении теста во время выполнения их на удаленных виртуальных машинах.
Давайте посмотрим, как можно создать простую страницу с результатами выполнения теста и панель мониторинга с помощью InfluxDB и Grafana.
Цель:
Мы будет собирать все доступные тестовые метрики, такие как:
- Статус теста-метода
- Продолжительность теста-метода
- Статус класса с тестовыми методами
- Время выполнения тестов одного класса
- Статус набора тестов
- Продолжительность выполнения набора тестов
Некоторые из показателей мы можем получить в режиме реального времени, как показано ниже:
- Количество методов тестирования, сгруппированных по статусу (например: Pass: 30, Failed: 2, Skipped: 2) в конкретный день.
- Тенденция продолжительности выполнения набора тестов за неделю, месяц, год и т.д.
InfluxDB:
InfluxDB — это база данных временных рядов, которая используется для сбора всех метрик тестов. InfluxDB имеет REST API для записи данных и отправки запросов. Больше вы можете узнать здесь. Ниже я использую команду docker для запуска экземпляра InfluxDB.
sudo docker run -p 8086:8086 -v $PWD:/var/lib/influxdb influxdb
Создание базы данных:
У нас уже поднята и запущена база данных InfluxDB. Давайте создадим отдельную схему базы данных для сбора результатов тестов Selenium. Ниже я запускаю команду в терминале, чтобы создать в базе данных схему под названием «selenium». (Проверьте URL адрес, замените localhost на hostname/ipaddress, если запускаете не на текущем компьютере).
curl -i -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE selenium"
TestNG:
Давайте создадим простой тест testNG:
public class SampleTest {
@Test(description = "login")
public void login(){
}
@Test(description = "search for flights", dependsOnMethods = "login")
public void search(){
}
@Test(description = "select flight", dependsOnMethods = "search")
public void select(){
}
@Test(description = "book flight", dependsOnMethods = "select")
public void book(){
}
@Test(description = "logout", dependsOnMethods = "book")
public void logout(){
}
}
Нашей целью является сбор результатов теста в InfluxDB во время выполнения. Итак, нам понадобится драйвер/библиотека в Java для InfluxDB.
Зависимости Maven:
Добавьте зависимости Maven, указанные далее:
org.influxdb
influxdb-java
2.12
Слушатели:
Слушатели (listeners) TestNG отлично подходят для прослушивания событий и могут реагировать в зависимости от произошедшего события. Сначала давайте создадим простой класс, который отвечает за отправку результатов в InfluxDB.
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.Point;
public class ResultSender {
private static final InfluxDB INFLXUDB = InfluxDBFactory.connect("http://localhost:8086", "root", "root");
private static final String DATABASE = "selenium";
static{
INFLXUDB.setDatabase(DATABASE);
}
public static void send(final Point point){
INFLXUDB.write(point);
}
}
Теперь создадим другой класс, который реализует интерфейс ITestListener.
import org.influxdb.dto.Point;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import java.util.concurrent.TimeUnit;
public class ExecutionListener implements ITestListener {
public void onTestStart(ITestResult iTestResult) {
}
public void onTestSuccess(ITestResult iTestResult) {
this.sendTestMethodStatus(iTestResult, "PASS");
}
public void onTestFailure(ITestResult iTestResult) {
this.sendTestMethodStatus(iTestResult, "FAIL");
}
public void onTestSkipped(ITestResult iTestResult) {
this.sendTestMethodStatus(iTestResult, "SKIPPED");
}
public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) {
}
public void onStart(ITestContext iTestContext) {
}
public void onFinish(ITestContext iTestContext) {
this.sendTestClassStatus(iTestContext);
}
private void sendTestMethodStatus(ITestResult iTestResult, String status) {
Point point = Point.measurement("testmethod")
.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.tag("testclass", iTestResult.getTestClass().getName())
.tag("name", iTestResult.getName())
.tag("description", iTestResult.getMethod().getDescription())
.tag("result", status)
.addField("duration", (iTestResult.getEndMillis() - iTestResult.getStartMillis()))
.build();
ResultSender.send(point);
}
private void sendTestClassStatus(ITestContext iTestContext) {
Point point = Point.measurement("testclass")
.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.tag("name", iTestContext.getAllTestMethods()[0].getTestClass().getName())
.addField("duration", (iTestContext.getEndDate().getTime() - iTestContext.getStartDate().getTime()))
.build();
ResultSender.send(point);
}
}
Примечание: Используйте дополнительный тег, отвечающий вашим задачам в приведенном выше примере, чтобы классифицировать результаты. Например tag («scenario», «login flow»).
Слушатель (listener) из примера выше будет мониторить выполнение теста и как только определенный метод/класс теста будет выполнен, он отправит имя, продолжительность и кое-какие дополнительные детали. Моя цель здесь — просто подкинуть вам идею. Меняйте код в соответствии с вашими нуждами.
Теперь добавьте слушателя в XML-пакет или в базовый класс TestNG.
Или же:
@Listeners(ExecutionListener.class)
public class SampleTest {
@Test
public void test(){
}
}
Grafana:
Мы добились отправки результатов в InfluxDB. Но как запрашивать результаты и визуализировать полученные данные? Для этого мы будет использовать другой бесплатный инструмент под названием «Grafana».
Grafana является отличным инструментом визуализации для данных временных рядов, она прекрасно взаимодействует с InfluxDB. Ниже приведены команды docker для создания экземпляра Grafana. [плагин piechart является необязательным в команде, его можно удалить, если в нем нет надобности]
docker run -d -p 3000:3000
--name=grafana \
-e "GF_INSTALL_PLUGINS=grafana-piechart-panel" \
-v $PWD:/var/lib/grafana \
grafana/grafana
Источник данных для Grafana:
Перейдите в Settings → Data sources → Add new data source, как показано на скриншоте. Нажмите на кнопку «Save & Test», чтобы удостовериться, что Grafana может общаться с InfluxDB.
Примечание: Если вы используете Grafana с Docker и пытаетесь получить доступ как «Server default», НЕ ИСПОЛЬЗУЙТЕ localhost в строке подключения к InfluxDB. Все потому, что здесь localhost — это контейнер Grafana, а не физическая машина. Таким образом контейнер Grafana не сможет найти InfluxDB.
Создание панели мониторинга:
Мне бы хотелось, чтобы вы посмотрели это видео, поскольку объяснить в статье все нюансы непросто. Именно для этого я записал отельное видео.
Демо 2:
Подведем итог:
Надеюсь, получение результатов в реальном времени с помощью InfluxDB и Grafana оказалось вам интересно и полезно. Оно требует минимальных изменений в существующей структуре, ведь мы используем слушателей TestNG. Удалить слушателя из файла набора/базового класса достаточно, чтобы отключить эту функцию, если вам она не нужна. Такой подход поможет избежать некой фрустрации в команде, если ее члены только и занимаются тем, что мониторят результаты тестов через консольный ввод/вывод на удаленной машине. В этой статье лишь изложена основная идея. Вы можете улучшить этот подход, добавив больше информации, например, тестовую среду, добавить дополнительные фильтры для обновления данных в диаграммах для конкретной среды/тестов и т.д.
Вот такой короткий, но довольно полезный материал. Традиционно ждем ваши комментарии, а также напоминаем о том, что уже сегодня пройдет день открытых дверей по курсу, записаться на который может каждый желающий.