Как известно, основной проблемой в тестировании является отчетность по прогонам. Некоторые компании собирают данные в отдельном хранилище. Вместо того, чтобы вручную организовывать хранение, было решено сохранять их в Test IT
. Такие данные как: исход, время выполнения и количество автоматизированных кейсов позволяют разделить тесты на выборки и дать оценку покрытия автотестами.
Это практично, поскольку в Test IT
всё сделали до нас и не придется заново изобретать велосипед. Объединив Test IT
и pytest
мы сможем выборочно запускать авто тесты. В итоге должна получиться мастер система, из которой будут запускаться тестовые выборки и собираться статистика.
Несмотря на то, что существует множество СУТ (Allure TestOps
, TestLink
и т.п.), решили остановится на Test IT
, поскольку это быстро растущий проект по доступной цене с поддержкой на русском языке, а лицензия на TestRail
уже закончилась.
Техническое задание
В рамках задачи следует:
- Настроить проект в
Test IT
- Настроить прохождение pytest-тестов в
GitLab CI
- Написать плагин для
pytest
который:
- создает автоматизированный кейс в
Test IT
- связывает автоматизированный и ручной кейс
- запускает только те автоматизированные кейсы, которые были выбраны в прогоне
- отмечает результаты в режиме реального времени
- создает автоматизированный кейс в
Замечания
- Для работы с Test IT Swagger API следует создать
API-secret-key
Реализация
1. Создание и связывание автоматизированных кейсов в Test IT
В Test IT
существует два вида кейсов: ручной и автоматизированный
Для того чтобы в прогоне появилась кнопка Launch Autotests
автоматизированный кейс должны быть создан и привязан к ручному
В таком случае напротив ручного кейса появится символ ракеты
Создание и связывание автоматизированного кейса происходит через endpoint AutoTests, в который следует передать два параметра:
- testit_case_title — название автоматизированного кейса;
- testit_case_id — идентификатор ручного кейса для привязки.
@pytest.mark.testit_case_id(29035) @putest.mark.testit_case_title("Проверка первой успешной загрузки файла") def test_download_first(test_it_configuration): """ Автотест прилинкованный к ручному тесту """ from pprint import pprint pprint(test_it_configuration) sleep(randint(a=0, b=8))
Для запуска GitLab CI агента через Test IT следует создать WebHook со следующими параметрами:
Параметры для GitLab CI:
- URL — ссылка на trigger от GIT-проекта;
- ref — ветка, в которой запускаются тесты;
- token — токин от GitLab CI триггера.
Параметры для запуска PYTEST:
- TEST_IT — флаг сообщающий, что тесты запущены из Test IT;
- TESTIT_URL — ссылка на Test IT;
- API_KEY — ключ для Test IT Swagger API;
- PROJECT_ID — идентификатор проекта в котором вы работаете;
- TEST_IT_MODE — режим работы с Test IT.
TEST_IT_MODE принимает следующие значения:
- DELETE_AUTOTESTS
- CREAT_AUTOTESTS
- LINK_AUTOTESTS
- RUN
Эти параметры будут переданы в GitLab CI и сохранены в переменных окружения агента
Тесты получают значения из переменных окружения агента при помощи модуля getenv
from os import getenv class TestItParams: """ Параметры из Test IT """ is_test_it = getenv('TEST_IT', 'False').lower().capitalize() == 'True' mode = getenv('TEST_IT_MODE', 'RUN') url = getenv('TESTIT_URL', 'http://tmslt-1.video.rt.ru/') key = getenv('API_KEY', None) project_id = getenv('PROJECT_ID', None) run_id = getenv('TEST_RUN_ID', None) configuration_id = getenv('CONFIG_ID', None)
Класс TestItParams следует сохранить в объекте session
def pytest_sessionstart(session): """ SetUP тестовый сессии: собрать env-параметры из TestIT """ session.test_it = TestItParams
Для создания автоматизированного кейса во время запуска pytest, нам нужно достать два параметра testit_case_title и testit_case_id.
Эти параметры можно получить из pytest_collection_modifyitems, поскольку он вызывается во время составления списка на запуск.
Для этого напишем plugin в файле conftest.py
def pytest_collection_modifyitems(session, items): """ Перехват состояния перед публикацией списка кейсов """ if session.test_it.is_test_it is True: print('Тесты запущены для TEST_IT') if 'DELETE_AUTOTESTS' in session.test_it.mode: delete_all_auto_test_from_project(pytest_session=session) if 'CREAT_AUTOTESTS' in session.test_it.mode: create_autotest_in_project(pytest_session=session, pytest_items=items) if 'LINK_AUTOTESTS' in session.test_it.mode: link_autotests_to_testcases(pytest_session=session, pytest_items=items) if 'RUN' in session.test_it.mode: select_autotest_from_testrun_only(pytest_session=session) else: print('\nПроходит штатный запуск')
Функции create_autotest_in_project и link_autotests_to_testcases это обычные API запросы через endpoint AutoTests.
Параметр test_it_mode используется для разделения задач: создание, привязка, удаление или запуск.
2. Выборочный запуск pytest-тестов
При создании тестового плана возникает потребность в запуске только выбранных автоматизированных кейсов.
Поскольку pytest
ничего не знает о тестовом плане, то он должен запрашивать его самостоятельно.
Для этого по значению параметра TEST_RUN_ID через endpoint TestRunes мы получаем список тестов в текущем прогоне.
Далее выбираем только те тесты, которые есть в прогоне и удаляем остальные.
def pytest_collection_modifyitems(session, items): """ Перехват состояния перед публикацией списка кейсов: создание, удаление, линковка, выборка """ if session.test_it.is_test_it is True: print('Тесты запущены для TEST_IT') if 'DELETE_AUTOTESTS' in session.test_it.mode: delete_all_auto_test_from_project(pytest_session=session) if 'CREAT_AUTOTESTS' in session.test_it.mode: create_autotest_in_project(pytest_session=session, pytest_items=items) if 'LINK_AUTOTESTS' in session.test_it.mode: link_autotests_to_testcases(pytest_session=session, pytest_items=items) if 'RUN' in session.test_it.mode: select_autotest_from_testrun_only(pytest_session=session) else: print('\nПроходит штатный запуск')
Фильтрация происходит в объекте session.items в момент составления списка на запуск.
def select_autotest_from_testrun_only(pytest_session): """ Выбрать для запуска только те кейсы, которые содержатся в тестовом прогоне """ run_api = TestRunes(pytest_session.test_it.url, pytest_session.test_it.key) current_test_run = run_api.get_testrun_by_id(pytest_session.test_it.run_id) external_ids = [] for case in current_test_run['testResults']: if case['startedOn'] is None: external_ids.append((case['autoTest']['externalId'], case['configuration'])) edited_session_items = [] for case in pytest_session.items: for external_id in external_ids: if case.name in external_id[0]: case.test_it_configuration = external_id[1] edited_session_items.append(case) pytest_session.items = edited_session_items
3. Возврат результата прохождения pytest-тестов
Каждый автоматизированный кейс должен получать результат прохождения в режиме реального времени а не постфактум.
Для возвращения статуса в реальном времени нам следует воспользоваться хуком pytest_runtest_makereport с декоратором @pytest.hookimpl(hookwrapper=True).
Он позволяет перехватывать выполнение ОДНОГО теста ДО и ПОСЛЕ прохождения.
@pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item): """ Перехватывает состояние каждого теста во время: setup и done """ outcome = yield if 'RUN' in item.session.test_it.mode: provide_test_results_into_run(pytest_session=item.session, pytest_outcome=outcome, pytest_item=item)
Этот хук возвращает объект outcome, в котором содержится информация о прогоне текущего теста.
Передача результатов прогона в Test IT происходит через endpoint TestRunes.
def provide_test_results_into_run(pytest_session, pytest_outcome, pytest_item): """ Предоставить результат выполнения теста в TestIT """ test_run_api = TestRunes(pytest_session.test_it.url, pytest_session.test_it.key) res = pytest_outcome.get_result() if res.when == "call": autotest_id = pytest_item.name outcome = res.outcome duration = res.duration message = '' traceback = '' if res.outcome == 'failed': message = res.longrepr.reprcrash.message traceback = res.longreprtext test_run_api.set_auto_test_results_for_test_run(run_id=pytest_session.test_it.run_id, autoTestExternalId=autotest_id, outcome=humanize(outcome), message=message, traces=traceback, duration=duration, configurationId=pytest_item.test_it_configuration['id'])
Вывод
Объединив Test IT и pytest мы собрали мастер систему которая умеет:
- запускать автотесты в GitLab CI;
- получать результат в режиме реального времени;
- собирать статистику по запускам;
- запускать выборки тестов.
Test IT имеет красивый интерфейс, предоставляющий кольцевые-диаграммы, различные таблицы и графики. Можно узнать, в каком прогоне упал конкретный тест и сколько времени он выполнялся.
Демонстрация
Ссылки
ссылка на оригинал статьи https://habr.com/ru/company/rostelecom/blog/695814/
Добавить комментарий