Does it work
Skill TsakunovR/does-it-work
Проверка, что продукт реально работает, и защита его качества автотестами. Аудит работающего (в т.ч. навайбкоженного) приложения: найти баги, оценить готовность к проду, выдать баг-репорт с 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", "тесты флакают", "ревью тестов", "проверь качество тестов".From its SKILL.md
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.
3 things to look at
- reads credentialsReads from 6 credential sources: `API_TESTS_*` and 5 more.
- 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.
- runs commandsInstructs the agent to run 8 commands, including `python <директория-скилла>/scripts/check_env.py https://stage.example.com/api [--token ...]` and 7 more.
SKILL.md
28.3 KB, ~7.2k tokens by cl100k_base, 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 соответствующего шаблона: прочитай его перед генерацией своей ветки.
What ships with it: 109 files
179.9 KB alongside SKILL.md, 40 of them executable
examples/
- bug-report.md2.6 KB
- coverage-map.md2.0 KB
reference/
- input-sources.md4.9 KB
- live-api-patterns.md11.8 KB
- stabilize-and-review.md7.0 KB
scripts/
- bootstrap-java.shruns850 B
- bootstrap.shruns1015 B
- check_env.pyruns3.7 KB
templates/
- api-java/allure-categories.json627 B
- api-java/.gitignore31 B
- api-java/pom.xml4.2 KB
- api-java/README.md6.0 KB
- api-java/src/test/java/booker/clients/AuthClient.java774 B
- api-java/src/test/java/booker/clients/BaseClient.java2.8 KB
- api-java/src/test/java/booker/clients/BookingsClient.java992 B
- api-java/src/test/java/booker/clients/HealthClient.java349 B
- api-java/src/test/java/booker/clients/RoomsClient.java342 B
- api-java/src/test/java/booker/clients/UsersClient.java736 B
- api-java/src/test/java/booker/config/TestConfig.java1.4 KB
- api-java/src/test/java/booker/models/ApiError.java441 B
- api-java/src/test/java/booker/models/Booking.java870 B
- api-java/src/test/java/booker/models/HealthResponse.java103 B
- api-java/src/test/java/booker/models/LoginResponse.java123 B
- api-java/src/test/java/booker/models/PaymentResponse.java228 B
- api-java/src/test/java/booker/models/RegisterResponse.java145 B
- api-java/src/test/java/booker/models/UserProfile.java479 B
- api-java/src/test/java/booker/models/UserPublic.java601 B
- api-java/src/test/java/booker/support/AllureEnvironmentListener.java2.2 KB
- api-java/src/test/java/booker/tests/AuthTests.java5.4 KB
- api-java/src/test/java/booker/tests/BaseTest.java1.7 KB
- api-java/src/test/java/booker/tests/BookingLifecycleTests.java7.1 KB
- api-java/src/test/java/booker/tests/HealthTests.java1.0 KB
- api-java/src/test/java/booker/tests/KnownBugsTests.java2.8 KB
- api-java/src/test/java/booker/utils/ApiAssertions.java1.6 KB
- api-java/src/test/java/booker/utils/TestDataFactory.java2.2 KB
- api-java/src/test/resources/allure.properties47 B
- api-java/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener41 B
- .gitignore188 B
- LICENSE1.0 KB
- README.md5.1 KB
69 more files not listed here. See all 109 in the repository.