Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Автоматизация: pytest plugin для flaky tests
flaky_detection_plugin

Автоматизация: pytest plugin для flaky tests

Пишем custom pytest plugin. Автоматическая детекция flaky tests, CI-интеграция, quality gates

Проектный якорь

  • После уроков про интеграции у нас есть список проблемных тестов. Плагин автоматизирует обнаружение медленных и flaky и сохраняет артефакты в CI.

Плагин скорости и стабильности

tests/plugins/stability.py:

import json import pytest def pytest_addoption(parser): parser.addoption("--slow-threshold", action="store", type=float, default=0.5) parser.addoption("--flaky-cache", action="store", default=None, help="путь к json со списком flaky") def pytest_configure(config): config.addinivalue_line("markers", "contract: контрактные тесты API") config.addinivalue_line("markers", "flaky: нестабильный тест, требует исправления") config._slow_tests = [] config._suspected_flaky = set() if cache := config.getoption("--flaky-cache"): try: with open(cache) as f: config._suspected_flaky = set(json.load(f)) except FileNotFoundError: config._suspected_flaky = set() @pytest.hookimpl(tryfirst=True) def pytest_runtest_setup(item): if item.nodeid in getattr(item.config, "_suspected_flaky", set()): item.add_marker(pytest.mark.xfail(reason="known flaky")) def pytest_runtest_logreport(report): if report.when != "call": return cfg = report.config threshold = cfg.getoption("--slow-threshold") if report.duration > threshold: cfg._slow_tests.append((report.nodeid, report.duration)) if report.failed and "flaky" in report.keywords: cfg._suspected_flaky.add(report.nodeid) @pytest.hookimpl(trylast=True) def pytest_sessionfinish(session, exitstatus): slow = sorted(session.config._slow_tests, key=lambda t: t[1], reverse=True) reporter = session.config.pluginmanager.get_plugin("terminalreporter") if slow: reporter.write_line("\n[slow-tests] топ медленных:", red=False, bold=True) for nodeid, duration in slow[:10]: reporter.write_line(f"{nodeid} - {duration:.3f}s") cache_path = session.config.getoption("--flaky-cache") if cache_path: with open(cache_path, "w") as f: json.dump(sorted(session.config._suspected_flaky), f, indent=2)

Запуск:

pytest -p tests.plugins.stability --slow-threshold=0.3 --flaky-cache=artifacts/flaky.json
  • Медленные тесты выводятся в терминал и сохраняются в артефакты CI.
  • Flaky помечаются xfail до исправления, чтобы не ронять сборку, но не забывать долг.

request.node и метрики

@pytest.fixture(autouse=True) def mark_contract_tests(request, metrics_client): if "contract" in request.keywords: metrics_client.increment("tests.contract")
  • Маркеры позволяют собирать метрики по типам тестов и навешивать политику запуска (-m "not contract" для быстрых прогонов).

Когда писать свой плагин

  • Нужно единое качество: обязательные таймауты, запрет глобального state, автодобавление маркеров.
  • Хотите переиспользовать инфраструктурные фикстуры/правила между несколькими сервисами.
  • Требуется расширить CLI опциями команды без копипаста в conftest.py.

Проверьте свои знания

Вопросы ещё не добавлены

Вопросы для этой подтемы ещё не добавлены.