add new
Some checks failed
K8S Fission Deployment / Deployment fission functions (push) Failing after 12s
Some checks failed
K8S Fission Deployment / Deployment fission functions (push) Failing after 12s
This commit is contained in:
187
.agents/skills/pytest/SKILL.md
Normal file
187
.agents/skills/pytest/SKILL.md
Normal file
@@ -0,0 +1,187 @@
|
||||
---
|
||||
name: pytest
|
||||
description: |
|
||||
Python testing with pytest framework for unit, integration, and API tests.
|
||||
Use when: (1) Writing test cases for Python code, (2) Setting up pytest fixtures,
|
||||
(3) Testing async functions with pytest-asyncio, (4) Mocking dependencies,
|
||||
(5) Parameterizing tests, (6) Testing FastAPI/Flask endpoints, (7) Setting up test coverage,
|
||||
(8) Creating test factories with factory_boy, (9) Configuring CI/CD test pipelines.
|
||||
---
|
||||
|
||||
# Pytest Testing Skill
|
||||
|
||||
Comprehensive testing patterns for Python applications using pytest.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Feature | Reference File |
|
||||
|---------|----------------|
|
||||
| Fixtures, conftest, scopes | [references/fixtures.md](references/fixtures.md) |
|
||||
| Async testing, pytest-asyncio | [references/async-testing.md](references/async-testing.md) |
|
||||
| Mocking, patching, spies | [references/mocking.md](references/mocking.md) |
|
||||
| FastAPI/Flask endpoint testing | [references/api-testing.md](references/api-testing.md) |
|
||||
|
||||
## Dependencies
|
||||
|
||||
```toml
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest>=8.0.0",
|
||||
"pytest-asyncio>=0.24.0",
|
||||
"pytest-cov>=4.1.0",
|
||||
"httpx>=0.28.0", # Async HTTP client for API tests
|
||||
"factory-boy>=3.3.0", # Test factories
|
||||
"faker>=33.0.0", # Fake data generation
|
||||
]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### pyproject.toml
|
||||
|
||||
```toml
|
||||
[tool.pytest.ini_options]
|
||||
asyncio_mode = "auto"
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py"]
|
||||
python_functions = ["test_*"]
|
||||
addopts = "-v --tb=short"
|
||||
filterwarnings = ["ignore::DeprecationWarning"]
|
||||
|
||||
[tool.coverage.run]
|
||||
source = ["app"]
|
||||
omit = ["*/tests/*", "*/__init__.py"]
|
||||
```
|
||||
|
||||
## Basic Test Structure
|
||||
|
||||
```python
|
||||
import pytest
|
||||
|
||||
# Simple test function
|
||||
def test_addition():
|
||||
assert 1 + 1 == 2
|
||||
|
||||
# Test class (group related tests)
|
||||
class TestCalculator:
|
||||
def test_add(self):
|
||||
assert add(2, 3) == 5
|
||||
|
||||
def test_subtract(self):
|
||||
assert subtract(5, 3) == 2
|
||||
|
||||
# Expected exceptions
|
||||
def test_division_by_zero():
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
divide(1, 0)
|
||||
|
||||
# Parametrized tests
|
||||
@pytest.mark.parametrize("input,expected", [
|
||||
(1, 1),
|
||||
(2, 4),
|
||||
(3, 9),
|
||||
])
|
||||
def test_square(input, expected):
|
||||
assert square(input) == expected
|
||||
```
|
||||
|
||||
## Fixtures
|
||||
|
||||
```python
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def sample_user():
|
||||
return {"name": "John", "email": "john@example.com"}
|
||||
|
||||
@pytest.fixture
|
||||
def db_connection():
|
||||
conn = create_connection()
|
||||
yield conn # Test runs here
|
||||
conn.close() # Cleanup after test
|
||||
|
||||
# Use fixture in test
|
||||
def test_user_name(sample_user):
|
||||
assert sample_user["name"] == "John"
|
||||
```
|
||||
|
||||
## Async Testing
|
||||
|
||||
```python
|
||||
import pytest
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_function():
|
||||
result = await async_operation()
|
||||
assert result == "success"
|
||||
|
||||
@pytest.fixture
|
||||
async def async_client():
|
||||
async with AsyncClient() as client:
|
||||
yield client
|
||||
```
|
||||
|
||||
## Mocking
|
||||
|
||||
```python
|
||||
from unittest.mock import patch, MagicMock, AsyncMock
|
||||
|
||||
def test_with_mock():
|
||||
with patch("module.external_api") as mock_api:
|
||||
mock_api.return_value = {"data": "mocked"}
|
||||
result = function_using_api()
|
||||
assert result["data"] == "mocked"
|
||||
mock_api.assert_called_once()
|
||||
|
||||
# Async mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_mock():
|
||||
with patch("module.async_call", new_callable=AsyncMock) as mock:
|
||||
mock.return_value = "result"
|
||||
result = await function_with_async_call()
|
||||
assert result == "result"
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest
|
||||
|
||||
# Verbose output
|
||||
pytest -v
|
||||
|
||||
# Run specific file
|
||||
pytest tests/test_users.py
|
||||
|
||||
# Run specific test
|
||||
pytest tests/test_users.py::test_create_user
|
||||
|
||||
# Run with coverage
|
||||
pytest --cov=app --cov-report=term-missing
|
||||
|
||||
# Stop on first failure
|
||||
pytest -x
|
||||
|
||||
# Run last failed tests
|
||||
pytest --lf
|
||||
|
||||
# Run tests matching pattern
|
||||
pytest -k "user and not delete"
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
project/
|
||||
├── app/
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ └── services/
|
||||
├── tests/
|
||||
│ ├── __init__.py
|
||||
│ ├── conftest.py # Shared fixtures
|
||||
│ ├── test_main.py
|
||||
│ └── test_services/
|
||||
└── pyproject.toml
|
||||
```
|
||||
Reference in New Issue
Block a user