Does it work
Skill TsakunovR/does-it-work
Claude Code / Codex skill: проверяет, что ваш продукт реально работает — находит баги и строит защиту от регрессий автотестами
npx -y skills add TsakunovR/does-it-workAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 10 stars10 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Проверка, что продукт реально работает, и защита его качества автотестами. Аудит работающего (в т.ч. навайбкоженного) приложения: найти баги, оценить готовность к проду, выдать баг-репорт с severity. Генерация тестовых фреймворков: API-тесты на Python (pytest + httpx + Pydantic + Allure) и Java (JUnit 5 + REST Assured), WEB/UI-тесты (Playwright, Selenium, Selenide, Page Object); конвертация OpenAPI/Postman/curl/HAR в тесты, негативные кейсы, контракты. Также стабилизация флакающих тестов и ревью качества тестов. Triggers: "проверь мой продукт/приложение", "найди баги", "навайбкодил", "можно ли в прод", "работает ли оно", "vibe code", "напиши автотесты", "сгенерируй тесты", "покрой тестами", "e2e тесты", "UI-тесты", "Playwright", "REST Assured", "generate tests", "стабилизируй тесты", "flaky", "тесты флакают", "ревью тестов", "проверь качество тестов".
SKILL.md
28.3 KB, as published. Nobody here has run it
does-it-work: проверка продукта и защита качества автотестами
Скилл отвечает на вопрос «а оно вообще работает?»: прогоняет живое приложение
тестами, находит баги (репорт с severity) и оставляет каркас автотестов как защиту
от регрессий. Пять эталонных каркасов в templates/ — все проверены запуском
против живых стендов. Копируйте их структуру и стиль, а не пишите с нуля.
Оформление (все ветки): имена функций/переменных — латиницей, docstrings, allure-тайтлы, шаги и тексты assert-сообщений — на русском.
Выбор ветки
| Задача | Стек | Шаблон |
|---|---|---|
| API-тесты на Python (дефолт для API) | pytest + httpx (sync) + Pydantic | templates/api-python/ |
| API-тесты на Java | JUnit 5 + REST Assured + Maven | templates/api-java/ |
| UI-тесты на Python (дефолт для WEB) | Playwright + Page Object | templates/web-python-playwright/ |
| UI-тесты на Python (легаси/требование) | Selenium + Page Object | templates/web-python-selenium/ |
| UI-тесты на Java | Selenide + JUnit 5 | templates/web-java-selenide/ |
Если тип (API/WEB) или язык не следует из запроса и контекста проекта — задай один вопрос пользователю до генерации. README каждого шаблона описывает паттерны своей ветки. Java- и WEB-шаблоны — проверенные примеры на реальном приложении RV Booker: замените ресурсы/страницы на свои, сохранив структуру слоёв.
Общие конвенции всех веток (подробно раскрыты ниже на python-ветке, остальные
зеркалят): слои клиенты/страницы → модели → тесты по фичам; конфиг только из
env-переменных (API_TESTS_* / WEB_TESTS_*); маркеры/теги smoke/critical/negative/flaky
- severity на каждом тесте; строгие контракты (Pydantic
extra="forbid"/ Jackson records); никаких sleep — только ожидания (wait_until/ Awaitility / встроенные в Playwright и Selenide); environment.properties и категории в Allure; зелёный прогон обязателен; «Самопроверка качества» и «Red flags» (секции ниже) применяются во всех ветках.
Специфика WEB-веток: Page Object (страница = класс, локаторы — свойства/константы, действия — методы с шагом); подготовка данных и логин — через API в обход UI (форма логина — отдельный тест); артефакты при падении (скриншот + HTML) в Allure; селекторы: стабильные id → роли → css, хрупкие xpath запрещены; мобильные вьюпорты и кросс-браузерная CI-матрица — в Playwright-шаблоне.
Маршрутизация: что читать под задачу
- «Проверь мой продукт / найди баги / можно ли в прод» (аудит навайбкоженного или незнакомого приложения) → те же шаги 1–5, но главный деливерабл — не каркас, а вердикт: префлайт стенда → smoke ядра → карта покрытия → баг-репорт с severity (examples/bug-report.md) и ответ «что работает, что сломано, что не проверено». Каркас остаётся пользователю как защита от регрессий.
- Новый проект с нуля → выбор ветки (таблица выше) + весь порядок работы (шаги 1–5).
- Дописать тесты в существующий проект → шаг 1 (режим «существующий»), шаги 2, 4, 5.
- Стабилизировать флакающие тесты → reference/stabilize-and-review.md, режим «Стабилизация»: воспроизведи повторами → классифицируй причину → почини причину, не симптом → докажи N зелёными прогонами. Каркас не разворачивай.
- Ревью существующих тестов → там же, режим «Ревью»: сначала запуск, потом чек-листы (включая шаг 5 ниже), находки с severity, отчёт до правок.
- Только негативные кейсы / контракты → шаг 2 + паттерны «негативные», «контракт» из шага 3; каркас не разворачивай.
- API с логином/ролями или общий стенд → плюс reference/live-api-patterns.md.
- WEB-тесты → README выбранного web-шаблона; разведай DOM живого приложения (Playwright-скриптом) до написания Page Object'ов — не выдумывай селекторы.
- Источник — не OpenAPI (код, требования, curl/HAR) → reference/input-sources.md.
- Стенд недоступен/сомнителен → сначала
scripts/check_env.py(см. шаг 2).
Порядок работы (шаги детализированы для api-python; остальные ветки зеркалят)
1. Определи режим
- Новый проект → разверни каркас из шаблона выбранной ветки, подставь реальные эндпоинты/страницы вместо примера.
- Существующий тестовый проект → сначала изучи его: conftest, базовый клиент, стиль
именования, маркеры. Новые тесты пиши в стиле проекта; паттерны из
templates/применяй только там, где в проекте нет своего решения. Не дублируй существующие фикстуры.
2. Извлеки тест-кейсы из источника
Источником может быть OpenAPI-спека, исходный код сервиса, текстовые требования или примеры запросов (curl/Postman/HAR). Рецепты по каждому — в reference/input-sources.md. Если источник неоднозначен — задай вопросы пользователю до генерации, не додумывай.
Перед генерацией проверь стенд префлайт-скриптом — он покажет доступность, латентность и работоспособность авторизации до того, как ты напишешь хоть один тест. Скрипт лежит в директории скилла, а cwd при работе — проект пользователя, поэтому вызывай его по полному пути к директории скилла:
python <директория-скилла>/scripts/check_env.py https://stage.example.com/api [--token ...]
Если в API больше ~15 операций — не генерируй вслепую: построй карту покрытия
(таблица «метод + путь → планируемые тесты»), согласуй с пользователем объём
(полное покрытие / ядро / конкретные фичи, образец —
examples/coverage-map.md) и сохрани карту в docs/coverage.md
сгенерированного проекта. По ней видно, что покрыто, а что осознанно отложено;
обновляй её при доработках.
3. Сгенерируй код по слоям
api-tests/
config.py # pydantic-settings: base_url, токены — из env (API_TESTS_*)
clients/
base.py # BaseApiClient: allure.step + вложения «Запрос»/«Ответ»
<resource>.py # клиент на ресурс: create/get/list/delete + create_raw
models/
<resource>.py # Pydantic-модели ответов, extra="forbid"
utils/
assertions.py # assert_status / assert_contract / assert_error (allure.step внутри)
waiters.py # wait_until: поллинг асинхронных операций вместо time.sleep
retry.py # retry-декоратор с экспоненциальным backoff (сетевые сбои)
soft.py # SoftAssertions: все расхождения одним отчётом
tests/
__init__.py # обязателен здесь и в каждой поддиректории (см. Gotchas)
conftest.py # http_client (2 режима), фабрики faker, created_* с teardown
<feature>/ # директория = фича; файл = сценарная группа, ≤1 класса на файл
__init__.py
test_lifecycle.py # happy path + полный жизненный цикл
test_validation.py # параметризованные негативные (400/404/422)
test_access.py # авторизация и доступ (401/403)
pytest.ini # testpaths, --alluredir, маркеры (см. таксономию ниже)
requirements.txt
.env.example # шаблон всех API_TESTS_*-переменных с комментариями
README.md # установка, запуск, переключение окружений, CI-матрица
allure-categories.json # категории дефектов Allure (копирует pytest_configure из conftest)
.github/workflows/api-tests.yml # CI: e2e по пушу/кнопке/расписанию, артефакт allure-results
Обязательные паттерны (все реализованы в templates/):
- Тесты не вызывают HTTP напрямую — только через методы клиентов. Клиент возвращает
httpx.Response, проверки статуса и тела — в тесте. - Проверки — через
utils/assertions.py, не голыми assert:assert_status(resp, 201),model = assert_contract(resp, UserResponse),assert_error(resp, 404, context=case_id)— каждый даёт Allure-шаг и читаемое сообщение; доменные проверки полей остаются обычными assert рядом. - Асинхронные операции — только
wait_untilизutils/waiters.py,time.sleepв тестах запрещён. Если API отвечает «принято в обработку» (202/processing) — это отдельный тест: дождись конечного статуса поллингом и проверь его. - Таксономия маркеров (registered в pytest.ini):
smoke— минимальный быстрый набор ключевых сценариев,critical— бизнес-критичные потоки,negative— негативные,flaky— карантин (CI гоняет-m "not flaky"). Плюс@allure.severityна каждом тесте: blocker — ключевые happy path, critical — авторизация/доступ, normal — остальное, minor — 404 и косметика. В web- и java-ветках дополнительно маркер/тегe2eна всех тестах (они всегда идут против живого стенда); в api-python его нет — режим e2e/asgi задаёт env-переменнаяAPI_TESTS_MODE, а не маркер. create_raw(payload: dict)в каждом клиенте — для негативных кейсов с произвольным телом.- Контракт через Pydantic:
UserResponse.model_validate(response.json())сextra="forbid"— ловит лишние поля, типы и обязательность. Тела ошибок тоже валидируются моделью (ApiError). - Негативные кейсы — один параметризованный тест, кейсы вида
("случай", payload), человекочитаемыйcase_idидёт в сообщение assert. - Тестовые данные — фабрики на
faker(фикстураuser_payload), никаких хардкодов. - Очистка — фикстура
created_*создаёт ресурс и удаляет в teardown; teardown не падает, если тест уже удалил ресурс сам. - Каждый негативный позитивному в пару: на любой happy path — минимум кейсы «невалидное тело» (422), «без авторизации» (401), «не существует» (404).
- Группировка по фиче, не по типу теста (выбор пользователя): директория = фича,
файл = сценарная группа, не больше одного класса на файл (класс в pytest — только
пространство имён и
allure.story). Негативные кейсы лежат рядом со своей фичей, а не в общем «негативном» файле; запуск фичи целиком —pytest tests/<feature>. Allure-иерархия: feature = директория, story = файл/класс. - README.md обязателен во всех ветках (шаблоны в
templates/): механизм переключения окружений должен быть виден без чтения config.py — примеры запуска в терминале и CI-матрица сред..env.exampleобязателен в python-ветках (pydantic-settings читает.env); в java-ветках dotenv-механизма нет — Java-стек читает env-переменные напрямую, поэтому вместо.env.exampleв README должна быть полная таблица env-переменных с описанием и дефолтами. - Живой стенд и динамическая авторизация — если токен не статический
(register/login, роли admin/user, общий стенд с чужими данными), бери проверенные
паттерны из reference/live-api-patterns.md:
session_user/temp_user, skip позитивного админского CRUD без кредов, ретрай при конфликте ресурсов, уникальные суффиксы в данных. Для ветки api-java — Java-эквиваленты там же (@BeforeAll-пользователь,@BeforeEach-temp-пользователь,Assumptions.assumeTrue, Awaitility).
4. Запусти и добейся зелёного прогона — обязательно
Сгенерированные, но не запущенные тесты — не результат. Установка и smoke-проверка
окружения — готовыми скриптами из директории скилла (запускать из корня
сгенерированного проекта, путь к скрипту — полный, до директории скилла):
python-ветки — scripts/bootstrap.sh (venv + зависимости + проверка коллекции
тестов), java-ветки — scripts/bootstrap-java.sh (проверка java/mvn +
mvn test-compile).
Что делает scripts/bootstrap.sh (эквивалент вручную, проверено):
uv venv .venv --python 3.12
uv pip install --python .venv/bin/python -r requirements.txt
PYTHONPATH=. .venv/bin/pytest --collect-only -q # проверка коллекции тестов
Интеграционный режим (in-process, без развёрнутого стенда — если приложение импортируемо):
API_TESTS_MODE=asgi PYTHONPATH=.:<путь-к-приложению> .venv/bin/pytest
E2E против стенда:
API_TESTS_BASE_URL=https://staging.example.com API_TESTS_API_TOKEN=... PYTHONPATH=. .venv/bin/pytest
Allure-результаты пишутся в allure-results/ (задано в pytest.ini); отчёт:
allure serve allure-results. Категории дефектов (allure-categories.json в корне
проекта) подкладывает в results хук pytest_configure из conftest — известные баги
(strict xfail с текстом «Баг API: …») попадают в отдельную категорию отчёта.
Тренды/история Allure появляются, только если переносить history/ из прошлого
отчёта в новые results — в CI сохраняйте отчёт артефактом или публикуйте на Pages.
Если тест падает из-за реального расхождения API со спекой —
не подгоняй тест под фактическое поведение молча: покажи расхождение пользователю.
Подтверждённый баг фиксируй тестом с xfail(reason="Баг API: ...", strict=True) —
прогон остаётся зелёным, а когда баг починят, тест сам просигналит (XPASS→FAILED).
Найденные баги API в итоговом отчёте пользователю классифицируй по severity (шаблон — examples/bug-report.md): Critical — потеря денег/данных, дыры авторизации; High — функция не работает или спека врёт о ключевом поведении; Medium — принимаются невалидные данные, неверные коды ошибок; Low — расхождения форматов, косметика.
5. Самопроверка качества — после зелёного прогона
Зелёный ≠ качественный. Пройди по сгенерированным тестам чек-листом; каждое «да» — чинить:
- Есть тест, который проверяет только статус-код, хотя ответ содержит тело? (слабый assert — добавь контракт/проверку полей)
- Есть проверки только «поле существует», где можно проверить значение?
- Тест зависит от результатов другого теста или от порядка запуска?
- В данных есть хардкоды (id, email, даты), которые сломаются на другом стенде?
- Название теста содержит «и» — он проверяет два поведения? Раздели.
- Негативный кейс проверяет только код ошибки, но не контракт тела ошибки?
- Happy path без пары негативных (401/404/невалидное тело)?
- Есть
time.sleepвместоwait_until? - Асинхронные операции API (202/processing) проверены до конечного статуса?
- Все тесты размечены маркерами и severity?
Red flags — сигналы остановиться
Если ловишь себя на одной из этих мыслей — остановись, это ошибка процесса:
| Мысль | Реальность |
|---|---|
«Ослаблю модель (extra="ignore", Any), чтобы прошло» | Это расхождение контракта — покажи пользователю, ослабляй только точечно с комментарием |
| «Поменяю ожидаемый статус на фактический, спека наверное устарела» | Может и устарела — но это решает пользователь, а не тест |
| «Тест против живого API прошёл с первого раза — отлично» | Проверь, что он вообще может упасть: сломай ожидание и убедись, что падает |
| «Этот эндпоинт слишком простой, чтобы тестировать» | Простые эндпоинты ломаются так же часто; health-check — самый дешёвый smoke |
| «Пропущу запуск, тесты очевидно корректные» | Незапущенные тесты — не результат (шаг 4 обязателен) |
| «Данные захардкожу, на этом стенде они всегда есть» | Стенд общий/пересоздаваемый — бери опорные данные запросом, генерируй свои фабрикой |
| «Флаки-тест перезапущу, наверное повезёт» | Разберись в причине; временно — маркер flaky (карантин), не игнор |
Режимы запуска и CI
- Переключение окружений — только через env-переменные
API_TESTS_*(см.config.py), без правок кода. Приоритет: переменная окружения →.env→ дефолт в config.py. Зафиксированное решение пользователя: не добавлять CLI-флаги (--base-urlчерезpytest_addoption) и плагины (pytest-base-url) — один источник правдыSettings, ноль лишних зависимостей; вместо этого механизм документируется в README (примеры терминала + CI-матрица, шаблон вtemplates/api-python/README.md). - Для CI:
pytest -m "not flaky"(карантин не валит регрессию; флаки гоняются отдельной джобой-m flaky),--alluredirуже включён; среда задаётся переменными джобы (матрица сред), секреты — только через env, не через флаги (флаги видны в логах CI). - Готовый workflow в
templates/api-python/.github/workflows/api-tests.yml— две джобы: прогон + публикация Allure-отчёта на GitHub Pages с переносомhistory/(тренды между прогонами копятся автоматически). - Моки внешних API (когда тестируем свой сервис in-process, а он ходит наружу) —
respx:respx.mockфикстурой, роуты на конкретные URL,assert_all_called. - Параллельность —
pytest-xdist(-n auto); тесты обязаны быть независимыми (свои данные через фабрики, очистка в teardown) — паттерны шаблона это гарантируют.
Gotchas (найдены при реальном прогоне)
EmailStrтребуетemail-validator: ставьтеpydantic[email], иначе падение на этапе сборки схемы модели (ImportErrorпри коллекции тестов).httpx.ASGITransport— только async. С синхроннымhttpx.Clientон падает сAttributeError: 'ASGITransport' object has no attribute 'handle_request'. Для sync in-process тестов используйтеfastapi.testclient.TestClient— он наследникhttpx.Client, поэтому API-клиенты каркаса работают с ним без изменений.- Кириллические id в
parametrizeв выводе терминала экранируются (\u043f\u0443...вместопу...) — это косметика pytest, в Allure-отчёте всё читаемо. Если мешает, добавьтеdisable_test_id_escaping_and_forfeit_all_rights_to_community_support = Trueв pytest.ini. TestClient(app, headers=...)принимает заголовки в конструкторе — токен авторизации задаётся один раз, как и у сетевого клиента.- Пустая env-переменная не «сбрасывает» настройку:
API_TESTS_BASE_URL= pytestзадаёт пустую строку (перекрывая и.env, и дефолт) — тесты падают сhttpx.UnsupportedProtocol. Проверяйте, не экспортирована ли переменная пустой. - Одинаковые имена тест-файлов в разных директориях (
users/test_validation.pyиbookings/test_validation.py) без__init__.pyроняют коллекцию pytest с «import file mismatch». Кладите пустой__init__.pyвtests/и каждую поддиректорию — заодно это делает надёжными импорты видаfrom tests.factories import.
Выше — gotchas ветки api-python. Gotchas остальных веток (api-java, все web) — в разделе «Gotchas» README соответствующего шаблона: прочитай его перед генерацией своей ветки.