Pytest Testing

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

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "Pytest Testing" with this command: npx skills add pluginagentmarketplace/custom-plugin-python/pluginagentmarketplace-custom-plugin-python-pytest-testing

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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

pandas data analysis

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

python fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

python performance

No summary provided by upstream source.

Repository SourceNeeds Review
Pytest Testing | V50.AI