pytest-skill — скилл для Claude Code: тесты pytest в Python
Скилл для ИИ-агентов, который пишет тесты pytest: фикстуры, parametrize, маркеры, мокинг и conftest. Пригодится, когда нужно покрыть Python-код тестами без ручной возни.
npx skills add LambdaTest/agent-skills --skill pytest-skill -a claude-codeЧто делает pytest-skill
Скилл даёт агенту готовые шаблоны pytest: базовые тесты, фикстуры с teardown через yield, @pytest.mark.parametrize, маркеры skip, skipif, xfail, мокинг через mocker и unittest.mock. Отдельная таблица антипаттернов показывает, чем assert x == y лучше self.assertEqual(), и почему состояние лучше держать в фикстурах, а не в __init__. Есть шпаргалка по запуску: pytest -m slow, pytest -k "login and not invalid", pytest --lf, pytest --cov=myapp --cov-report=html.
Внутри — раздел с настройкой pyproject.toml: testpaths, список маркеров, addopts. Для глубоких сценариев есть reference/playbook.md с разделами про асинхронные тесты на pytest-asyncio, фабрики фикстур, tmp_path, CI/CD через GitHub Actions и таблицу из 10 частых проблем с решениями. Параллельный запуск через pytest -n auto требует pytest-xdist — без него флаг не сработает.
Скилл ставится одной командой через npx skills add и работает в Claude, Codex, Cursor, GitHub Copilot, Gemini CLI и OpenCode. Агенту достаточно упомянуть pytest или conftest в запросе, чтобы он подхватил шаблоны.
Какие задачи решает
- написать фикстуру с корректным teardown через yield
- разбить один большой тест на несколько мелких
- замокать внешний HTTP-вызов через mocker.patch
- пометить медленные тесты маркером и запускать только их
- настроить маркеры и покрытие в pyproject.toml
Примеры запросов агенту
- Напиши тесты pytest для модуля myapp/calculator.py с фикстурами
- Добавь parametrize для функции validate_email с несколькими кейсами
- Замокай requests.get в myapp/service.py и проверь обработку ответа
Как установить pytest-skill
1Через Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill pytest-skill -a claude-code2Вручную: положить файлы
~/.claude/skills/pytest-skill/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/pytest-skill/
1Через Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill pytest-skill -a codex2Вручную: положить файлы
.agents/skills/pytest-skill/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill pytest-skill -a cursor2Вручную: положить файлы
.cursor/skills/pytest-skill/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install LambdaTest/agent-skills pytest-skill2Вручную: положить файлы
.github/skills/pytest-skill/SKILL.md1Через Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill pytest-skill -a gemini-cli2Командой платформы
gemini skills install https://github.com/LambdaTest/agent-skills --path pytest-skillВручную: положить файлы
.devin/skills/pytest-skill/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add LambdaTest/agent-skills --skill pytest-skill -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Вопросы о pytest-skill
Как установить pytest-skill в Claude?
Выполните npx skills add LambdaTest/agent-skills --skill pytest-skill -a claude-code. Скилл появится в ~/.claude/skills/pytest-skill/SKILL.md.
Что делает pytest-skill?
Генерирует тесты pytest: фикстуры, parametrize, маркеры, мокинг и паттерны conftest. Агент применяет их, когда в запросе есть pytest, conftest или Python test.
Какие плагины нужны для параллельного запуска и асинхронных тестов?
Для pytest -n auto нужен pytest-xdist, для асинхронных тестов — pytest-asyncio. Оба упомянуты в playbook скилла.
Исходный текст
SKILL.md · MIT
---
name: pytest-skill
description: >
Generates production-grade pytest tests in Python with fixtures, parametrize,
markers, mocking, and conftest patterns. Use when user mentions "pytest",
"conftest", "@pytest.fixture", "@pytest.mark", "Python test". Triggers on:
"pytest", "conftest", "Python test", "parametrize", "Python unit test".
languages:
- Python
category: unit-testing
license: MIT
metadata:
author: TestMu AI
version: "1.0"
---
# Pytest Testing Skill
## Core Patterns
### Basic Test
```python
import pytest
def test_addition():
assert 2 + 3 == 5
def test_exception():
with pytest.raises(ValueError, match="invalid"):
int("not_a_number")
class TestCalculator:
def test_add(self):
calc = Calculator()
assert calc.add(2, 3) == 5
def test_divide_by_zero(self):
with pytest.raises(ZeroDivisionError):
Calculator().divide(10, 0)
```
### Fixtures
```python
@pytest.fixture
def calculator():
return Calculator()
@pytest.fixture
def db_connection():
conn = Database.connect("test_db")
yield conn # teardown after yield
conn.rollback()
conn.close()
@pytest.fixture(scope="module")
def api_client():
client = APIClient(base_url="http://localhost:8000")
yield client
client.logout()
# conftest.py - shared fixtures
@pytest.fixture(autouse=True)
def reset_state():
State.reset()
yield
State.cleanup()
# Usage
def test_add(calculator):
assert calculator.add(2, 3) == 5
```
### Parametrize
```python
@pytest.mark.parametrize("input,expected", [
("hello", 5), ("", 0), ("pytest", 6),
])
def test_string_length(input, expected):
assert len(input) == expected
@pytest.mark.parametrize("a,b,expected", [
(2, 3, 5), (-1, 1, 0), (0, 0, 0),
])
def test_add(calculator, a, b, expected):
assert calculator.add(a, b) == expected
```
### Markers
```python
@pytest.mark.slow
def test_large_dataset(): ...
@pytest.mark.skip(reason="Not implemented")
def test_future_feature(): ...
@pytest.mark.skipif(sys.platform == "win32", reason="Unix only")
def test_unix_permissions(): ...
@pytest.mark.xfail(reason="Known bug #123")
def test_known_bug(): ...
```
### Mocking
```python
from unittest.mock import patch, MagicMock
def test_send_email(mocker):
mock_smtp = mocker.patch("myapp.email.smtplib.SMTP")
send_welcome_email("[email protected]")
mock_smtp.return_value.sendmail.assert_called_once()
def test_api_call(mocker):
mock_response = mocker.Mock()
mock_response.status_code = 200
mock_response.json.return_value = {"users": [{"name": "Alice"}]}
mocker.patch("myapp.service.requests.get", return_value=mock_response)
users = get_users()
assert len(users) == 1
@patch("myapp.service.database")
def test_save_user(mock_db):
mock_db.save.return_value = True
assert save_user({"name": "Alice"}) is True
mock_db.save.assert_called_once()
```
### Assertions
```python
assert x == y
assert x != y
assert x in collection
assert isinstance(obj, MyClass)
assert 0.1 + 0.2 == pytest.approx(0.3)
with pytest.raises(ValueError) as exc_info:
raise ValueError("bad")
assert "bad" in str(exc_info.value)
```
### Anti-Patterns
| Bad | Good | Why |
|-----|------|-----|
| `self.assertEqual()` | `assert x == y` | pytest rewrites give better output |
| Setup in `__init__` | `@pytest.fixture` | Lifecycle management |
| Global state | Fixture with `yield` | Proper cleanup |
| Huge test functions | Small focused tests | Easier debugging |
## Quick Reference
| Task | Command |
|------|---------|
| Run all | `pytest` |
| Run file | `pytest tests/test_login.py` |
| Run specific | `pytest tests/test_login.py::test_login_success` |
| By marker | `pytest -m slow` |
| By keyword | `pytest -k "login and not invalid"` |
| Verbose | `pytest -v` |
| Stop first fail | `pytest -x` |
| Last failed | `pytest --lf` |
| Coverage | `pytest --cov=myapp --cov-report=html` |
| Parallel | `pytest -n auto` (pytest-xdist) |
## pyproject.toml
```toml
[tool.pytest.ini_options]
testpaths = ["tests"]
markers = ["slow: slow tests", "integration: integration tests"]
addopts = "-v --tb=short"
```
## Deep Patterns
For production-grade patterns, see `reference/playbook.md`:
| Section | What's Inside |
|---------|--------------|
| §1 Config | pytest.ini + pyproject.toml with markers, coverage |
| §2 Fixtures | Scoping, factories, teardown, autouse, tmp_path |
| §3 Parametrize | Basic, with IDs, cartesian, indirect |
| §4 Mocking | pytest-mock, monkeypatch, spies, env vars |
| §5 Async | pytest-asyncio, async fixtures, async client |
| §6 Exceptions | pytest.raises(match=), warnings |
| §7 Markers & Plugins | Custom markers, collection hooks |
| §8 Class-Based | Nested classes, autouse setup |
| §9 CI/CD | GitHub Actions matrix, coverage gates |
| §10 Debugging Table | 10 common problems with fixes |
| §11 Best Practices | 15-item production checklist |
© TestMu AI · MIT · LambdaTest/agent-skills