AgentSkillsCN

Python Testing

Python测试

SKILL.md

Python Testing

pytest patterns, Factory Boy, and DRF test strategies.

Factory Boy

python
# apps/users/tests/factories.py
import factory
from apps.users.models import User

class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = User

    email = factory.Sequence(lambda n: f"user{n}@example.com")
    name = factory.Faker("name")
    role = "member"
    is_active = True

class AdminFactory(UserFactory):
    role = "admin"

Fixtures

python
# conftest.py
import pytest
from rest_framework.test import APIClient
from apps.users.tests.factories import UserFactory

@pytest.fixture
def api_client():
    return APIClient()

@pytest.fixture
def user():
    return UserFactory()

@pytest.fixture
def auth_client(api_client, user):
    api_client.force_authenticate(user=user)
    return api_client

DRF Endpoint Tests

python
class TestUserEndpoints:
    def test_create_user(self, auth_client):
        payload = {"email": "new@example.com", "name": "New User"}
        response = auth_client.post("/api/users/", payload)

        assert response.status_code == 201
        assert response.data["email"] == "new@example.com"
        assert User.objects.filter(email="new@example.com").exists()

    def test_create_user_duplicate_email(self, auth_client, user):
        payload = {"email": user.email, "name": "Duplicate"}
        response = auth_client.post("/api/users/", payload)

        assert response.status_code == 400

    def test_list_users_unauthenticated(self, api_client):
        response = api_client.get("/api/users/")
        assert response.status_code == 401

Service Tests

python
class TestUserService:
    def test_create_user_sends_welcome_email(self, mocker):
        mock_send = mocker.patch("apps.users.services.EmailService.send_welcome")
        user = UserService.create_user(email="test@example.com", name="Test")

        assert user.email == "test@example.com"
        mock_send.assert_called_once_with(user=user)

    def test_create_user_creates_audit_log(self):
        user = UserService.create_user(email="test@example.com", name="Test")
        assert AuditLog.objects.filter(action="user_created", target=user).exists()

Parametrize

python
@pytest.mark.parametrize("role,expected_status", [
    ("admin", 200),
    ("member", 403),
    ("viewer", 403),
])
def test_delete_user_permissions(auth_client, user, role, expected_status):
    user.role = role
    user.save()
    response = auth_client.delete(f"/api/users/{user.id}/")
    assert response.status_code == expected_status

Commands

bash
pytest --cov=apps -x                    # Standard run
pytest -k "test_create"                 # Filter by name
pytest apps/users/ -x --tb=short        # Single app, fast feedback
pytest --cov=apps --cov-report=html     # Coverage report