Selenium WebDriver – Метрика тестов в реальном времени с использованием Grafana и InfluxDB +8


Всем привет! Уже на следующей неделе стартуют занятия в группе «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, указанные далее:

<dependency>
            <groupId>org.influxdb</groupId>
            <artifactId>influxdb-java</artifactId>
            <version>2.12</version>
 </dependency>


Слушатели:


Слушатели (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.

<suite name="My suite">
    <listeners>
        <listener class-name="com.tag.realtime.ExecutionListener" />
    </listeners>
    <test name="Test1">
        <classes>
            <class name="com.tag.realtime.SampleTest"/>
        </classes>
    </test>
    <test name="Test2">
        <classes>
            <class name="com.tag.realtime.Sample2Test"/>
        </classes>
    </test>
</suite>


Или же:

@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. Удалить слушателя из файла набора/базового класса достаточно, чтобы отключить эту функцию, если вам она не нужна. Такой подход поможет избежать некой фрустрации в команде, если ее члены только и занимаются тем, что мониторят результаты тестов через консольный ввод/вывод на удаленной машине. В этой статье лишь изложена основная идея. Вы можете улучшить этот подход, добавив больше информации, например, тестовую среду, добавить дополнительные фильтры для обновления данных в диаграммах для конкретной среды/тестов и т.д.

Вот такой короткий, но довольно полезный материал. Традиционно ждем ваши комментарии, а также напоминаем о том, что уже сегодня пройдет день открытых дверей по курсу, записаться на который может каждый желающий.




К сожалению, не доступен сервер mySQL