Pytest Testing

Pytest Testing

Master test-driven development with pytest, fixtures, mocking, and CI/CD integration

2スター
1フォーク
更新日 1/23/2026
SKILL.md
readonlyread-only
name
Pytest Testing
description

Master test-driven development with pytest, fixtures, mocking, and CI/CD integration

version
"2.1.0"

Pytest Testing

Overview

Master software testing with pytest, Python's most popular testing framework. Learn test-driven development (TDD), write maintainable tests, and ensure code quality through comprehensive testing strategies.

Learning Objectives

  • Write unit, integration, and functional tests with pytest
  • Use fixtures for test setup and teardown
  • Mock external dependencies effectively
  • Implement test-driven development (TDD)
  • Measure and improve code coverage
  • Integrate tests with CI/CD pipelines

Core Topics

1. Pytest Basics

  • Test discovery and naming conventions
  • Assertions and comparison
  • Test organization (files, classes, modules)
  • Running tests (command-line options)
  • Markers and test selection
  • Parametrized tests

Code Example:

# test_calculator.py
import pytest

def add(a, b):
    return a + b

def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

# Basic test
def test_add():
    assert add(2, 3) == 5
    assert add(-1, 1) == 0
    assert add(0, 0) == 0

# Test exceptions
def test_divide_by_zero():
    with pytest.raises(ValueError, match="Cannot divide by zero"):
        divide(10, 0)

# Parametrized test
@pytest.mark.parametrize("a,b,expected", [
    (10, 2, 5),
    (20, 4, 5),
    (100, 10, 10),
    (-10, 2, -5),
])
def test_divide(a, b, expected):
    assert divide(a, b) == expected

# Test with marker
@pytest.mark.slow
def test_complex_operation():
    # This test takes a long time
    result = sum(range(1000000))
    assert result == 499999500000

2. Fixtures & Test Setup

  • Fixture scopes (function, class, module, session)
  • Fixture dependencies
  • Parametrized fixtures
  • Built-in fixtures (tmpdir, capsys, monkeypatch)
  • conftest.py for shared fixtures

Code Example:

# conftest.py
import pytest
import tempfile
from pathlib import Path

@pytest.fixture
def sample_data():
    """Provide sample data for tests"""
    return {
        'users': [
            {'id': 1, 'name': 'Alice', 'email': 'alice@example.com'},
            {'id': 2, 'name': 'Bob', 'email': 'bob@example.com'},
        ]
    }

@pytest.fixture
def temp_file():
    """Create temporary file for testing"""
    with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
        f.write("Test data")
        temp_path = f.name
    yield temp_path
    # Cleanup
    Path(temp_path).unlink()

@pytest.fixture(scope='module')
def database_connection():
    """Module-scoped database connection"""
    db = DatabaseConnection('test.db')
    db.connect()
    yield db
    db.close()

# test_users.py
def test_user_count(sample_data):
    assert len(sample_data['users']) == 2

def test_user_names(sample_data):
    names = [user['name'] for user in sample_data['users']]
    assert 'Alice' in names
    assert 'Bob' in names

def test_file_operations(temp_file):
    content = Path(temp_file).read_text()
    assert content == "Test data"

3. Mocking & Test Doubles

  • unittest.mock basics
  • Mocking functions and methods
  • Patching objects
  • Mock assertions
  • Side effects and return values
  • Testing with external dependencies

Code Example:

# api_client.py
import requests

class APIClient:
    def __init__(self, base_url):
        self.base_url = base_url

    def get_user(self, user_id):
        response = requests.get(f"{self.base_url}/users/{user_id}")
        response.raise_for_status()
        return response.json()

    def create_user(self, user_data):
        response = requests.post(f"{self.base_url}/users", json=user_data)
        response.raise_for_status()
        return response.json()

# test_api_client.py
from unittest.mock import Mock, patch
import pytest

@patch('api_client.requests.get')
def test_get_user(mock_get):
    # Setup mock
    mock_response = Mock()
    mock_response.json.return_value = {'id': 1, 'name': 'Alice'}
    mock_response.raise_for_status.return_value = None
    mock_get.return_value = mock_response

    # Test
    client = APIClient('https://api.example.com')
    user = client.get_user(1)

    # Assertions
    assert user['name'] == 'Alice'
    mock_get.assert_called_once_with('https://api.example.com/users/1')

@patch('api_client.requests.post')
def test_create_user(mock_post):
    # Setup mock
    mock_response = Mock()
    mock_response.json.return_value = {'id': 3, 'name': 'Charlie'}
    mock_post.return_value = mock_response

    # Test
    client = APIClient('https://api.example.com')
    user_data = {'name': 'Charlie', 'email': 'charlie@example.com'}
    result = client.create_user(user_data)

    # Assertions
    assert result['id'] == 3
    mock_post.assert_called_once_with(
        'https://api.example.com/users',
        json=user_data
    )

4. Coverage & CI/CD Integration

  • Measuring code coverage with pytest-cov
  • Coverage reports (terminal, HTML, XML)
  • Setting coverage thresholds
  • GitHub Actions integration
  • GitLab CI integration
  • Pre-commit hooks

Code Example:

# pytest.ini
[tool:pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts =
    --cov=myapp
    --cov-report=html
    --cov-report=term-missing
    --cov-fail-under=80
    -v

# .github/workflows/test.yml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install dependencies
        run: |
          pip install -r requirements.txt
          pip install pytest pytest-cov
      - name: Run tests
        run: |
          pytest --cov=myapp --cov-report=xml
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage.xml

# Command line usage
# Run all tests
pytest

# Run with coverage
pytest --cov=myapp

# Generate HTML coverage report
pytest --cov=myapp --cov-report=html

# Run specific test file
pytest tests/test_api.py

# Run tests with marker
pytest -m slow

# Run tests with verbose output
pytest -v

# Stop on first failure
pytest -x

Hands-On Practice

Project 1: Calculator TDD

Build a calculator using test-driven development.

Requirements:

  • Write tests BEFORE implementation
  • Basic operations (add, subtract, multiply, divide)
  • Error handling (division by zero)
  • Scientific operations (power, sqrt, log)
  • Test coverage > 90%

Key Skills: TDD workflow, parametrized tests, exception testing

Project 2: API Testing Suite

Create comprehensive test suite for a REST API.

Requirements:

  • Mock HTTP requests
  • Test CRUD operations
  • Error handling tests
  • Authentication tests
  • Integration tests
  • CI/CD pipeline setup

Key Skills: Mocking, fixtures, integration testing

Project 3: Database Testing

Test database operations with fixtures and transactions.

Requirements:

  • Setup test database fixture
  • Test CRUD operations
  • Transaction rollback
  • Data validation
  • Performance tests
  • Coverage report

Key Skills: Database fixtures, cleanup, performance testing

Assessment Criteria

  • [ ] Write clear, maintainable tests
  • [ ] Use fixtures appropriately
  • [ ] Mock external dependencies effectively
  • [ ] Achieve >80% code coverage
  • [ ] Follow TDD principles
  • [ ] Integrate tests with CI/CD
  • [ ] Write meaningful assertions

Resources

Official Documentation

Learning Platforms

Tools

Next Steps

After mastering pytest, explore:

  • Property-based testing - Hypothesis library
  • Performance testing - pytest-benchmark
  • Mutation testing - mutmut
  • Load testing - Locust, pytest-load

You Might Also Like

Related Skills

fix

fix

243Kdev-testing

Use when you have lint errors, formatting issues, or before committing code to ensure it passes CI.

facebook avatarfacebook
入手
peekaboo

peekaboo

179Kdev-testing

Capture and automate macOS UI with the Peekaboo CLI.

openclaw avataropenclaw
入手
frontend-testing

frontend-testing

128Kdev-testing

Generate Vitest + React Testing Library tests for Dify frontend components, hooks, and utilities. Triggers on testing, spec files, coverage, Vitest, RTL, unit tests, integration tests, or write/review test requests.

langgenius avatarlanggenius
入手
frontend-code-review

frontend-code-review

127Kdev-testing

Trigger when the user requests a review of frontend files (e.g., `.tsx`, `.ts`, `.js`). Support both pending-change reviews and focused file reviews while applying the checklist rules.

langgenius avatarlanggenius
入手
code-reviewer

code-reviewer

92Kdev-testing

Use this skill to review code. It supports both local changes (staged or working tree) and remote Pull Requests (by ID or URL). It focuses on correctness, maintainability, and adherence to project standards.

google-gemini avatargoogle-gemini
入手
session-logs

session-logs

90Kdev-testing

Search and analyze your own session logs (older/parent conversations) using jq.

moltbot avatarmoltbot
入手