Интеграция с системами отчётов
Механизм отчётов служит для представления результатов тестирования в презентационной форме. Он позволяет создавать пользовательские интеграции с инструментами построения отчётов (например 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 | Превышение времени выполнения теста |
| skip_test | Пропуск теста |
| stop_test | Остановка теста |
| close | Завершение всех тестов |
Каждый из этих методов будет вызван при наступлении соответствующего события. Все методы кроме close принимают данные о состоянии прохождения теста в виде экземпляра класса ReportData.
ReportData
Объект класса ReportData предоставляет информацию о выполнении текущего действия (т.е. команды с параметрами) и содержит следующие атрибуты:
| Метод | Тип данных | Описание |
|---|---|---|
| is_parent | bool | Текущее действие выполняется в субтесте или субстепе |
| parent_uuid | str | Идентификатор родительского теста или субтеста |
| attempt | int | Количество перезапусков |
| retries | int | Максимальное количество перезапусков |
| repeated | int | Количество последовательных запусков |
| action_name | str | Наименование текущего действия |
| status | str | Статус текущего действия |
| step_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_scope | dict | Пространство имён теста |
| file_line | str | Имя файла с исходным кодом теста и номер строки для текущего действия |
| arguments | ([], {}) | Позиционные и именованные аргументы для текущего действия |
| logs | dict | Словарь логов selenium-а (только для метода stop_test) |
| cookies | dict | Словарь cookies (только при ошибке) |
| links | dict | Словарь ссылок с дополнительной информацией о тестировании |
| message | [str] | Текст сообщений |
| description | str | Описание теста или шага |
| warning | [str] | Текст предупреждений |
| screenshot | [(str, bytes)] | Список пар: (“заголовок”, скриншот). Скриншиты в виде байт в формате png |
| page_name | str | Заголовок страницы |
| page_source | str | Исходник страницы (только при ошибке) |
| device | (str, str, str) | Возвращает тройку (платформа, устройство/архитектура, имя_устройства) |
Значение атрибута screenshot, cookies и page_source будет доступно только при вызове специальной команды или при возникновении ошибки.
Статусы действий и тестов
Для отслеживания состояния выполнения команд и тестов существуют статусы. Каждая команда завершается с тем или иным статусом. Если команда завершилась с ошибкой или предупреждением, то всему тесту будет присвоен соответствующий статус. Просмотреть статусы команд можно в режиме отладки.
Статусы шагов и команд:
| Статус | Описание |
|---|---|
| PASSED | Команда успешно завершилась |
| SKIPPED | Команда была пропущена |
| WARNING | Статус теста был переведён в WARNING |
| FAILED | Статус теста был переведён в FAILED |
| FATAL | Статус теста был переведён в FATAL |
| TIMEOUT | Статус теста был переведён в TIMEOUT |
| ERROR | Статус теста был переведён в ERROR |
| SKIP_TEST | Статус теста был переведён в SKIPPED |
| STOPPED | Статус теста был переведён в STOPPED |
Статусы тестов:
| Статус | Описание |
|---|---|
| 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 skip_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()))Пользовательские атрибуты тестов
Если система отчётов оперирует данными которые не предусмотрены в стандартной модели описания теста, то их можно добавить через пользовательский атрибуты тестов, а потом получить через атрибут test_args объекта отчёта.
Например расширение report_allure добавляет следующие дополнительные атрибуты: epic, feature, story, issue, owner, tms_link.
Добавить пользовательский атрибут можно при помощи класса ItemTestConfig из модуля core_dsl.
ItemTestConfig(name, data_type, default [, description ] [, desirialize ] [, validator ])
Создаёт описание атрибута теста. Класс принимает следующие параметры:
| Аргумент | Описание |
|---|---|
| name | Идентификатор параметра |
| data_type | Тип данных |
| default | Значение по умолчанию |
| description | Краткое описание параметра По умолчанию - ““ |
| desirialize | Функция десериализатор По умолчанию - None |
| validator | Функция валидатор По умолчанию - None |
Параметр default может быть определён как функция. В этом случае ей будет перед запуском теста будет передаваться его объект.
Значение параметров desirialize и validator аналогично одноимённым параметров класса ItemConfig.
ItemTestConfig.registrator(описание параметра {описание параметра})
Регистрирует одно или несколько описаний атрибута теста.
Пример:
from core_dsl import ItemTestConfig
# Регистрируем атрибуты теста
ItemTestConfig.registrator(
ItemTestConfig("owner", str, "")
, ItemTestConfig("tms_link", str, "")
)
# Теперь в тесте можно их определить
TEST["атрибуты"](
....
, owner="admin"
, tms_link="https://example.com/tms/123"
)
# И в объекте отчёта можно получить их значение
class Allure(BaseReport):
def start(self, report):
obj = TestResult(name=report.test_title, uuid=report.test_id, start=get_time(report))
if report.test_args["owner"]:
obj.labels.append(Label(name="owner", value=report.test_args["owner"]))
if report.test_args["tms_link"]:
obj.links.append(Link(LinkType.TEST_CASE, report.test_args["tms_link"]))Для версии 1.1 редакция от 22.11.2025
Telegramm группа
Политика конфиденциальности
Персональные данные