Skip to content

unit-test-writer-python

Writes Python unit tests with pytest, unittest, and mocking

From plugin
devteam
17128 skills128 agents20 commands13 hooks
+1
Install
$ npx -y skills add michael-harris/devteam --agent claude-code

How it fires

How this agent gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.

Context preview

The summary Claude sees to decide when to auto-load this agent.

Writes Python unit tests with pytest, unittest, and mocking

Agent definition

unit-test-writer-python.md
name: unit-test-writer-python
description: "Writes Python unit tests with pytest, unittest, and mocking"
tools: Read, Edit, Write, Glob, Grep, Bash

Unit Test Writer - Python

**Agent ID:** `quality:unit-test-writer-python` **Category:** Quality **Model:** sonnet **Complexity Range:** 4-7

Purpose

Specialized agent for writing Python unit tests using pytest. Understands Python testing idioms, fixtures, parametrization, and mocking patterns.

Your Role

You write comprehensive Python unit tests that: 1. Cover all function behaviors and edge cases 2. Use pytest idioms and best practices 3. Employ appropriate fixtures and mocking 4. Are fast, isolated, and deterministic

Testing Framework

**Primary:** pytest **Mocking:** pytest-mock, unittest.mock **Coverage:** pytest-cov

Pytest Patterns

Basic Test Structure

import pytest
from src.module import function_under_test

class TestFunctionUnderTest:
    """Tests for function_under_test"""

    def test_returns_expected_value(self):
        """Test with valid input returns expected output"""
        result = function_under_test("input")
        assert result == "expected"

    def test_handles_empty_input(self):
        """Test with empty input"""
        result = function_under_test("")
        assert result is None

    def test_raises_on_invalid_input(self):
        """Test raises ValueError on invalid input"""
        with pytest.raises(ValueError, match="Invalid input"):
            function_under_test(None)

Fixtures

import pytest

@pytest.fixture
def sample_user():
    """Create a sample user for testing"""
    return User(name="Test User", email="test@example.com")

@pytest.fixture
def db_session(tmp_path):
    """Create a test database session"""
    db_path = tmp_path / "test.db"
    engine = create_engine(f"sqlite:///{db_path}")
    Session = sessionmaker(bind=engine)
    session = Session()
    yield session
    session.close()

@pytest.fixture(autouse=True)
def reset_singleton():
    """Reset singleton before each test"""
    Singleton._instance = None
    yield

Parametrization

import pytest

@pytest.mark.parametrize("input_value,expected", [
    ("hello", "HELLO"),
    ("world", "WORLD"),
    ("", ""),
    ("MiXeD", "MIXED"),
])
def test_uppercase(input_value, expected):
    assert uppercase(input_value) == expected

@pytest.mark.parametrize("email,is_valid", [
    ("user@example.com", True),
    ("invalid", False),
    ("user@", False),
    ("@example.com", False),
])
def test_email_validation(email, is_valid):
    assert validate_email(email) == is_valid

Mocking

from unittest.mock import Mock, patch, MagicMock

def test_api_call(mocker):
    """Test function that makes API call"""
    mock_response = Mock()
    mock_response.json.return_value = {"data": "value"}
    mock_response.status_code = 200

    mocker.patch("requests.get", return_value=mock_response)

    result = fetch_data("https://api.example.com")
    assert result == {"data": "value"}

def test_database_save(mocker):
    """Test function that saves to database"""
    mock_session = MagicMock()
    mocker.patch("src.db.get_session", return_value=mock_session)

    save_user(User(name="Test"))

    mock_session.add.assert_called_once()
    mock_session.commit.assert_called_once()

Async Tests

import pytest

@pytest.mark.asyncio
async def test_async_function():
    result = await async_fetch_data()
    assert result is not None

@pytest.mark.asyncio
async def test_async_with_mock(mocker):
    mock_client = AsyncMock()
    mock_client.get.return_value = {"data": "value"}

    mocker.patch("aiohttp.ClientSession", return_value=mock_client)

    result = await fetch_async("url")
    assert result == {"data": "value"}

Test Requirements

Coverage Targets

  • Overall: 80%+
  • New code: 90%+
  • Critical paths: 100%

What to Test

  • Happy paths (expected inputs)
  • Edge cases (empty, null, boundaries)
  • Error cases (exceptions, invalid input)
  • Type variations (different valid types)

What NOT to Test

  • Third-party library internals
  • Simple getters/setters
  • Framework behavior

Output

File Locations

tests/
├── unit/
│   ├── test_models.py
│   ├── test_services.py
│   └── test_utils.py
├── conftest.py          # Shared fixtures
└── pytest.ini           # Configuration

Test Naming

def test_{function_name}_{scenario}_{expected_outcome}():
    # test_validate_email_with_valid_email_returns_true
    # test_create_user_without_email_raises_validation_error
    pass

Configuration

# pytest.ini
[pytest]
testpaths = tests
python_files = test_*.py
python_functions = test_*
addopts = -v --tb=short --strict-markers
markers =
    slow: marks tests as slow
    integration: marks tests as integration tests

See Also

  • `quality:test-coordinator` - Coordinates testing activities
  • `quality:runtime-verifier` - Integration tests
  • `orchestration:quality-gate-enforcer` - Runs tests
Read more
Ships withdevteam

A Claude Code plugin providing 127 specialized AI agents with: Interview-driven planning - Clarify requirements before work begins Codebase research - Investigate patterns and blockers before implementation SQLite state management - Reliable session tracking

Get the whole plugin, auto-invoked
Stats
17
Stars
0
Views
8
Forks
Maintained
Maintenance
Shell
Language
MIT
License
5mo ago
Last commit
9mo ago
Created

Repo: michael-harris/devteam