Интеграция с системами отчётов

Механизм отчётов служит для представления результатов тестирования в презентационной форме. Он позволяет создавать пользовательские интеграции с инструментами построения отчётов (например Allure Report или ReportPortal), TMS, системами логирования или отправлять информацию о прохождении тестов через телекомуникационные средства связи.

В месте с дистрибутивом поставляется расширения console и allure добавляющие возможность выводить информацию о тестировании на консоль и интегрировать тесты с инструментом Allure Report.

Для описания собственного расширения отчётов необходимо создать отдельный python скрипт в каталоге extensions. В этот скрипт нужно поместить описание класса отчёта который должен наследоваться от класса BaseReport.

BaseReport

В классе отчёта можно переопределить следующие методы:

Метод Событие
start Запуск теста
start_step Переход на новый шаг
stop_step Завершение шага
sub_test Запуск субтеста
message Вывод сообщения
error Вывод сообщения об ошибке
warning Вывод предупреждения
action Выполнение команды (работает на любом действии в том числе и с ошибкой)
test_error Ошибка теста FAIL
fatal_error Ошибка теста FATAL
timeout_error Превышение времени выполнения теста
scip_test Пропуск теста
stop_test Остановка теста
close Завершение всех тестов

Каждый из этих методов будет вызван при наступлении соответствующего события. Все методы кроме close принимают данные о состоянии прохождения теста в виде экземпляра класса ReportData.

ReportData

Объект класса ReportData предоставляет информацию о выполнении текущего действия (т.е. команды с параметрами) и содержит следующие атрибуты:

Метод Тип данных Описание
is_parent bool Текущее действие выполняется в субтесте или субстепе
parent_uuid str Идентификатор родительского теста или субтеста
attempt int Количество перезапусков
repeated int Количество последовательных запусков
action_name str Наименование текущего действия
status str Статус текущего действия/шага
value str Значение возвращённое действием
debug [(str, str)] Список пар (“идентификатор”, “значение”)
thread_id str Идентификатор потока в котором запущен тест
timestamp timestamp Время запуска теста
time float Длительность выполнения текущей команды
timeout float Тайм-аут для текущего действия
url str Адрес текущей страницы
browser_name str Название браузера
browser_version str Версия браузера
step_title str Заголовок шага
step_uuid str Идентификатор шага
step_args dict Аргументы шага
step_time float Время выполнения текущего шага
step_parent_uuid str Идентификатор родительского шага
script str Идентификатор текущего скрипта
script_args dict Аргументы текущего скрипта
test_name str Наименование теста
test_title str Заголовок теста
test_id str Идентификатор теста
test_args dict Аргументы теста
test_status str Статус теста
test_parameters dict Параметры с которыми был запущен тест
test_retries int Максимальное количество перезапусков для теста
test_scope dict Пространство имён теста
file_line str Имя файла с исходным кодом теста и номер строки для текущего действия
arguments ([], {}) Позиционные и именованные аргументы для текущего действия
logs dict Словарь логов selenium-а (только для метода stop_test)
cookies dict Словарь cookies (только при ошибке)
links dict Словарь ссылок с дополнительной информацией о тестировании
message [str] Текст сообщений
description str Описание теста или шага
warning [str] Текст предупреждений
screenshot [bytes] Список скриншотов окна браузера или отдельных элементов в формате png
page_name str Заголовок страницы
page_source str Исходник страницы (только при ошибке)

Значение атрибута screenshot, cookies и page_source будет доступно только при вызове специальной команды или при возникновении ошибки.

Статусы тестов

Статус Описание
UNKNOWN Тест не запускался
STARTED Тест был запущен, но не завершился
PASSED Тест успешно завершился
RETRO Тест успешно завершился, но не с первой попытки
WARNING Тест завершился с предупреждением
FAILED Тест завершился с ошибкой инварианта
FATAL Тест завершился с критической ошибкой
TIMEOUT Не хватило выделенного времени для завершения теста
ERROR Инфраструктурная ошибка
XFAILED Негативный тест завершился без ошибки
XPASSED Негативный тест завершился с ошибкой
SKIPPED Тест был пропущен
STOPPED Тест был остановлен

Пример

Ниже приведён пример простого расширения которое записывает в лог ход выполнения тестов:

#!/usr/bin/python3
# coding: utf-8

import os
import time

from report import BaseReport
from parameter import CONFIG, ItemConfig

ItemConfig.registrator(
    ItemConfig("TEXT_LOG_FILE", str, os.path.abspath("report.log"), "Путь к файлу лога")
)

class TextLog(BaseReport):
    def __init__(self):
        self._bufer     = {}
        self._log_file  = CONFIG.TEXT_LOG_FILE
        
        with open(self._log_file, "a") as log:
            log.write("%s\tSTART\t%s\n"%(str(time.time()), CONFIG.TEST_CASE_PATH))
    
    def _bufirezator(self, test_id, data):
        if not test_id in self._bufer:
            self._bufer[test_id] = []
        self._bufer[test_id].append(data)
    
    def start(self, report):
        if report.attempt > 0:
            title = "Перезапуск (%i/%i)" % (report.attempt, report.retries)
        if report.is_parent:
            title = "Субтест %s" % report.test_title
        else:
            title = "%s (%s)" % (report.test_title, report.browser_name)
        self._bufirezator(report.test_id, title)
        if report.test_description:
            self._bufirezator(report.test_id, report.test_description)
        if report.test_parameters:
            self._bufirezator(report.test_id, report.test_parameters)
    
    def start_step(self, report):
        self._bufirezator(report.test_id, "Запуск теста %s..." % report.step_title)
    
    def sub_test(self, report):
        self._bufirezator(report.test_id, "Запуск субтеста %s..." % report.message)
    
    def message(self, report):
        self._bufirezator(report.test_id, report.message)
    
    def error(self, report):
        self._bufirezator(report.test_id, "Ошибка в действии " + report.action_name)
    
    def warning(self, report):
        self._bufirezator(report.test_id, "Предупреждение: %s %s" % (report.action_name, report.warning))
    
    def test_error(self, report):
        self._bufirezator(report.test_id, "Ошибка в действии " + report.action_name)
    
    def fatal_error(self, report):
        self._bufirezator(report.test_id, "Фатальная ошибка в действии " + report.action_name)
    
    def timeout_error(self, report):
        self._bufirezator(report.test_id, "Превышение времени выполнения теста")
    
    def scip_test(self, report):
        self._bufirezator(report.test_id, "Тест пропущен!")
        self.stop_test(report)
    
    def stop_test(self, report):
        self._bufirezator(report.test_id, report.test_status)
        with open(self._log_file, "a") as log:
            for x in self._bufer.pop(report.test_id):
                log.write("\n"+x)
            log.write("\n\n")
    
    def close(self):
        with open(self._log_file, "a") as log:
            log.write("\nSTOP: %s"%str(time.time()))