Files
lab_ai/.agents/skills/pytest/SKILL.md
Nguyen Duc Thao 3861b027b2
Some checks failed
K8S Fission Deployment / Deployment fission functions (push) Failing after 12s
add new
2026-01-26 23:07:28 +07:00

4.1 KiB

name, description
name description
pytest 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
Async testing, pytest-asyncio references/async-testing.md
Mocking, patching, spies references/mocking.md
FastAPI/Flask endpoint testing references/api-testing.md

Dependencies

[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

[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

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

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

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

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

# 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