金色时刻 · 15:48
让好资源,触手可及
AGENT SKILL

test-writer

test-writer 是面向测试与安全的 Agent Skill,来自 MaksimZayats/fastdjango。查看技能说明、操作步骤与使用约定,并通过原项目了解详细用法。

Writes tests using IoC overrides and test factories.

SKILL.md

下载 MD ↓
nametest-writer
descriptionWrites tests using IoC overrides and test factories.
version1.0.0

Test Writer Skill

This skill guides you through writing tests for this codebase using the established test patterns with IoC container overrides and test factories.

Quick Reference: Test Locations

Test Type Location When to Use
HTTP API integration tests/integration/http/<domain>/ Testing controllers via HTTP
Celery task integration tests/integration/tasks/ Testing background tasks
Unit tests tests/unit/<domain>/ Testing services in isolation

Core Testing Patterns

1. Function-Scoped Container (Isolation)

Every test gets a fresh IoC container:

from infrastructure.frameworks.punq import AutoRegisteringContainer
from ioc.container import ContainerFactory


@pytest.fixture(scope="function")
def container() -> AutoRegisteringContainer:
    container_factory = ContainerFactory()
    return container_factory()

This enables: - Complete test isolation - Per-test IoC overrides for mocking - No shared state between tests

2. Test Factories

Available factories in tests/integration/factories.py:

Factory Creates Usage
TestClientFactory HTTP test client test_client_factory(auth_for_user=user)
TestUserFactory Test users user_factory(username="test")
TestCeleryWorkerFactory Celery worker context with celery_worker_factory():
TestTasksRegistryFactory Task registry tasks_registry_factory()

3. IoC Override Pattern

Critical: Override BEFORE creating factories.

@pytest.mark.django_db(transaction=True)
def test_with_mock(
    container: AutoRegisteringContainer,
    user_factory: TestUserFactory,
) -> None:
    # 1. Create mock
    mock_service = MagicMock(spec=SomeService)
    mock_service.some_method.return_value = expected_value

    # 2. Override BEFORE creating test client
    container.register(SomeService, instance=mock_service)

    # 3. Create test client (uses mock)
    user = user_factory()
    test_client_factory = TestClientFactory(container=container)
    with test_client_factory(auth_for_user=user) as test_client:
        # 4. Make request
        response = test_client.get("/v1/endpoint/")

    # 5. Assert
    assert response.status_code == HTTPStatus.OK
    mock_service.some_method.assert_called_once()

HTTP API Test Template

@pytest.mark.django_db(transaction=True)
def test_create_success(self, test_client_factory: TestClientFactory, user: User) -> None:
    with test_client_factory(auth_for_user=user) as test_client:
        response = test_client.post("/v1/<domain>s/", json={"name": "Test"})

    assert response.status_code == HTTPStatus.OK

Full CRUD test template: See references/testing-new-features.md

Celery Task Test Template

with celery_worker_factory():
    result = registry.<task_name>.delay().get(timeout=5)
assert result == expected_value

Full task test patterns: See references/test-scenarios.md

Mocking Patterns

Mock Return Value

mock_service = MagicMock(spec=ProductService)
mock_service.get_by_id.return_value = Product(id=1, name="Test")

Mock Exception

mock_service = MagicMock(spec=ProductService)
mock_service.get_by_id.side_effect = ProductNotFoundError("Not found")

Verify Mock Called

mock_service.get_by_id.assert_called_once_with(product_id=1)
mock_service.create.assert_called_with(name="Test", price=99.99)

Test Markers

Marker When to Use
@pytest.mark.django_db Any test accessing database
@pytest.mark.django_db(transaction=True) Integration tests (required)
@pytest.mark.slow Tests > 1 second

Running Tests

# All tests with coverage
make test

# Specific file
pytest tests/integration/http/<domain>/test_<domain>.py -v

# Specific class
pytest tests/integration/http/<domain>/test_<domain>.py::TestCreate<Model> -v

# With coverage report
pytest --cov=src --cov-report=html

Creating a Custom Test Factory

class Test<Model>Factory(ContainerBasedFactory):
    def __call__(self, user: User, name: str = "Test") -> <Model>:
        return self._container.resolve(<Domain>Service).create(user_id=user.pk, name=name)

Full factory + fixture pattern: See references/testing-new-features.md

Common Testing Scenarios

See references/test-scenarios.md for: - User-scoped resource tests - Error handling tests - Pagination tests - Rate limiting tests - Async controller tests

Documentation

For detailed testing guidance: - Tutorial: docs/en/tutorial/06-testing.md - IoC overrides: docs/en/how-to/override-ioc-in-tests.md

来源:MaksimZayats/fastdjango · MIT 许可 · 许可原文 · MD 为来源页保存的历史版本