# 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", "тесты флакают", "ревью тестов", "проверь качество тестов".

- Skill: `tsakunovr/does-it-work` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add tsakunovr/does-it-work`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tsakunovr/does-it-work/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: TsakunovR (https://skillmd.com/u/tsakunovr)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tsakunovr/does-it-work

---


# 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-шаблоне.

## Маршрутизация: что читать под задачу

- **«Проверь мой продукт / найди баги / можно ли в прод»** (аудит навайбкоженного
  или незнакомого приложения) → главный деливерабл — не каркас, а вердикт.
  Порядок: префлайт стенда → **чек-лист аудита**
  ([reference/prod-readiness.md](reference/prod-readiness.md): авторизация, утечки,
  целостность данных, фаззинг по OpenAPI) → smoke ядра → карта покрытия →
  **баг-репорт с severity** ([examples/bug-report.md](examples/bug-report.md)) →
  **вердикт go/no-go** ([examples/prod-readiness-report.md](examples/prod-readiness-report.md))
  с обязательным разделом «что НЕ проверено». Чек-лист идёт раньше каркаса: типичное
  вайб-кодовое приложение сыпется на первом же блоке, и полдня на Page Object'ы до
  этого — не то, за чем к вам пришли. Каркас (шаги 1–5) остаётся пользователю как
  защита от регрессий, покрытие начинается с мест, где нашлись Critical/High.
- **Новый проект с нуля** → выбор ветки (таблица выше) + весь порядок работы (шаги 1–5);
  детали api-python (структура, паттерны с кодом, режимы запуска, gotchas) —
  [reference/api-python.md](reference/api-python.md), детали остальных веток —
  README их шаблонов.
- **Дописать тесты в существующий проект** → шаг 1 (режим «существующий»), шаги 2, 4, 5.
- **Стабилизировать флакающие тесты** →
  [reference/stabilize-and-review.md](reference/stabilize-and-review.md), режим
  «Стабилизация»: воспроизведи повторами (`scripts/flake_hunt.sh -n 10 -- <команда>`)
  → классифицируй причину → почини причину, не симптом → докажи N зелёными прогонами
  подряд (`--prove`). Каркас не разворачивай.
- **Ревью существующих тестов** → там же, режим «Ревью»: сначала запуск, потом
  чек-листы (включая шаг 5 ниже), находки с severity, отчёт до правок.
- **Только негативные кейсы / контракты** → шаг 2 + паттерны «негативные», «контракт»
  из шага 3; каркас не разворачивай.
- **API с логином/ролями или общий стенд** → плюс
  [reference/live-api-patterns.md](reference/live-api-patterns.md).
- **WEB-тесты** → README выбранного web-шаблона; разведай DOM живого приложения
  (Playwright-скриптом) до написания Page Object'ов — не выдумывай селекторы.
- **Источник — не OpenAPI** (код, требования, curl/HAR) →
  [reference/input-sources.md](reference/input-sources.md).
- **Стенд недоступен/сомнителен** → сначала `scripts/check_env.py` (см. шаг 2).

## Порядок работы (общий для всех веток; детали ветки — по ссылкам в шагах)

### 1. Определи режим

- **Новый проект** → разверни каркас из шаблона выбранной ветки, подставь реальные
  эндпоинты/страницы вместо примера.
- **Существующий тестовый проект** → сначала изучи его: conftest, базовый клиент, стиль
  именования, маркеры. Новые тесты пиши в стиле проекта; паттерны из `templates/`
  применяй только там, где в проекте нет своего решения. Не дублируй существующие фикстуры.

### 2. Извлеки тест-кейсы из источника

Источником может быть OpenAPI-спека, исходный код сервиса, текстовые требования или
примеры запросов (curl/Postman/HAR). Рецепты по каждому — в
[reference/input-sources.md](reference/input-sources.md). Если источник неоднозначен —
задай вопросы пользователю до генерации, не додумывай.

Перед генерацией проверь стенд префлайт-скриптом — он покажет доступность,
латентность и работоспособность авторизации до того, как ты напишешь хоть один тест.
Скрипт лежит в директории скилла, а cwd при работе — проект пользователя, поэтому
вызывай его по полному пути к директории скилла:

```bash
python <директория-скилла>/scripts/check_env.py https://stage.example.com/api [--token ...]
```

Если в API больше ~15 операций — не генерируй вслепую: построй **карту покрытия**
(таблица «метод + путь → планируемые тесты»), согласуй с пользователем объём
(полное покрытие / ядро / конкретные фичи, образец —
[examples/coverage-map.md](examples/coverage-map.md)) и сохрани карту в `docs/coverage.md`
сгенерированного проекта. По ней видно, что покрыто, а что осознанно отложено;
обновляй её при доработках.

### 3. Сгенерируй код по слоям

Полная структура каркаса, код паттернов и разбор каждого пункта —
[reference/api-python.md](reference/api-python.md) (эталон — `templates/api-python/`;
остальные ветки зеркалят её, синтаксис — в README своего шаблона). Коротко:

```
config.py  clients/  models/  utils/  tests/<feature>/  pytest.ini  .env.example  README.md
```

Принципы, обязательные во всех ветках:

- **Тесты не ходят в HTTP/DOM напрямую** — только через клиентов и Page Object'ы.
- **Проверки — через утилиты** (`assert_status` / `assert_contract` / `assert_error`),
  а не голыми assert: Allure-шаг и читаемое сообщение бесплатно.
- **Контракт ответа проверяется моделью** с `extra="forbid"` — включая тела ошибок.
- **Никаких sleep** — только ожидания (`wait_until`, Awaitility, встроенные ожидания
  Playwright и Selenide). Асинхронный ответ (202/processing) — отдельный тест
  с поллингом до конечного статуса.
- **Каждому happy path — негативные в пару**: невалидное тело (422), без авторизации
  (401), не существует (404); негативные — одним параметризованным тестом
  с человекочитаемым `case_id`.
- **Данные — фабрики** (faker), очистка — в teardown, teardown не падает на уже
  удалённом ресурсе. Хардкодов id/email/дат нет.
- **Таксономия разметки**: маркеры/теги `smoke`, `critical`, `negative`, `flaky`
  (карантин, CI гоняет `-m "not flaky"`) + `@allure.severity` на каждом тесте
  (blocker — ключевые happy path, critical — авторизация, normal — остальное,
  minor — 404 и косметика). В web- и java-ветках дополнительно тег `e2e`.
- **Группировка по фиче, не по типу теста**: директория = фича, файл = сценарная
  группа, ≤1 класса на файл. Allure-иерархия: feature = директория, story = файл.
- **README.md обязателен во всех ветках**, `.env.example` — в python-ветках
  (в java вместо него таблица env-переменных в README).
- **Живой стенд и динамическая авторизация** (register/login, роли, общие данные) —
  паттерны из [reference/live-api-patterns.md](reference/live-api-patterns.md),
  там же Java-эквиваленты.

### 4. Запусти и добейся зелёного прогона — обязательно

Сгенерированные, но не запущенные тесты — не результат. Разворачивание окружения —
скриптами из директории скилла (запускать из корня сгенерированного проекта,
путь к скрипту — полный): python-ветки — `scripts/bootstrap.sh` (venv +
зависимости + проверка коллекции), java-ветки — `scripts/bootstrap-java.sh`.

Режимы запуска, Allure-артефакты и заглушка API на случай «стенда нет вообще» —
[reference/api-python.md](reference/api-python.md).

Если тест падает из-за реального расхождения API со спекой — не подгоняй тест
под фактическое поведение молча: покажи расхождение пользователю. Подтверждённый
баг фиксируй тестом с `xfail(reason="Баг API: ...", strict=True)` — прогон остаётся
зелёным, а когда баг починят, тест сам просигналит (XPASS→FAILED).

Найденные баги классифицируй по severity (шаблон —
[examples/bug-report.md](examples/bug-report.md)): **Critical** — потеря денег/данных,
дыры авторизации; **High** — функция не работает или спека врёт о ключевом поведении;
**Medium** — принимаются невалидные данные, неверные коды ошибок; **Low** —
расхождения форматов, косметика.

### 5. Самопроверка качества — после зелёного прогона

Зелёный ≠ качественный. Сначала прогони линтер — он проверяет механическую часть
чек-листа детерминированно (python- и java-ветки):

```bash
python <директория-скилла>/scripts/review_tests.py .            # порог падения — high
python <директория-скилла>/scripts/review_tests.py . --json     # машиночитаемо
```

Находит: тесты без единой проверки, проверки только статус-кода, `sleep`, секреты
и URL в коде, хрупкие xpath, `extra="ignore"`, `xfail` без `strict`, отсутствие
severity, карантин без комментария, пропущенные `__init__.py`. Эталонные шаблоны
проходят его без единой находки — сгенерированный код обязан тоже.
**Ноль находок линтера — не отмазка от чтения кода:** дальше глазами по чек-листу,
каждое «да» — чинить:

- Есть тест, который проверяет **только статус-код**, хотя ответ содержит тело?
  (слабый 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/`
  (тренды между прогонами копятся автоматически).
- **Jenkins**: в каждом шаблоне лежит `Jenkinsfile` (declarative pipeline) —
  параметры стенда и объёма прогона, секреты через `credentials()`, публикация
  Allure шагом `allure`. Падение тестов помечает сборку UNSTABLE, а не FAILURE:
  иначе отчёт не соберётся именно тогда, когда он нужнее всего. Тренды и история
  в Jenkins работают из коробки — плагин сам переносит `history` между сборками,
  копировать вручную (как для Pages) не нужно. Требуемые плагины и имена установок
  инструментов — в шапке каждого `Jenkinsfile`.

## Чего скилл не делает

Говорите об этом прямо и заранее, а в аудите — отдельным разделом отчёта:
нагрузочное и стресс-тестирование; пентест (SQLi/XSS/SSRF-эксплуатация, инфраструктура,
зависимости); аудит исходного кода как таковой; мобильные приложения (Appium);
визуальные регрессии (скриншотное сравнение); тестирование на соответствие
(152-ФЗ, GDPR). Непроверенное, выданное за проверенное, вреднее ненайденного бага.

## Gotchas

Грабли, найденные реальными прогонами, — в ветке, где они водятся:
api-python — [reference/api-python.md](reference/api-python.md), остальные ветки —
раздел «Gotchas» в README своего шаблона. **Прочитай их до генерации кода**:
половина из них ломает прогон ещё на коллекции тестов.

