Install
$ agentstack add skill-tsakunovr-does-it-work-does-it-work ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
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](examples/bug-report.md)) и ответ «что работает, что сломано, что не проверено». Каркас остаётся пользователю как защита от регрессий.
- Новый проект с нуля → выбор ветки (таблица выше) + весь порядок работы (шаги 1–5).
- Дописать тесты в существующий проект → шаг 1 (режим «существующий»), шаги 2, 4, 5.
- Стабилизировать флакающие тесты →
[reference/stabilize-and-review.md](reference/stabilize-and-review.md), режим «Стабилизация»: воспроизведи повторами → классифицируй причину → почини причину, не симптом → докажи N зелёными прогонами. Каркас не разворачивай.
- Ревью существующих тестов → там же, режим «Ревью»: сначала запуск, потом
чек-листы (включая шаг 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).
Порядок работы (шаги детализированы для api-python; остальные ветки зеркалят)
1. Определи режим
- Новый проект → разверни каркас из шаблона выбранной ветки, подставь реальные
эндпоинты/страницы вместо примера.
- Существующий тестовый проект → сначала изучи его: conftest, базовый клиент, стиль
именования, маркеры. Новые тесты пиши в стиле проекта; паттерны из templates/ применяй только там, где в проекте нет своего решения. Не дублируй существующие фикстуры.
2. Извлеки тест-кейсы из источника
Источником может быть OpenAPI-спека, исходный код сервиса, текстовые требования или примеры запросов (curl/Postman/HAR). Рецепты по каждому — в [reference/input-sources.md](reference/input-sources.md). Если источник неоднозначен — задай вопросы пользователю до генерации, не додумывай.
Перед генерацией проверь стенд префлайт-скриптом — он покажет доступность, латентность и работоспособность авторизации до того, как ты напишешь хоть один тест. Скрипт лежит в директории скилла, а cwd при работе — проект пользователя, поэтому вызывай его по полному пути к директории скилла:
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. Сгенерируй код по слоям
api-tests/
config.py # pydantic-settings: base_url, токены — из env (API_TESTS_*)
clients/
base.py # BaseApiClient: allure.step + вложения «Запрос»/«Ответ»
.py # клиент на ресурс: create/get/list/delete + create_raw
models/
.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
/ # директория = фича; файл = сценарная группа, ≤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/. 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](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](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
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: TsakunovR
- Source: TsakunovR/does-it-work
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.