Claude Code Plugins

Community-maintained marketplace

Feedback

Guides test creation for Polibase following strict testing standards. Activates when writing tests or creating test files. Enforces external service mocking (no real API calls), async/await patterns, test independence, and proper use of pytest-asyncio to prevent CI failures and API costs.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name test-writer
description Guides test creation for Polibase following strict testing standards. Activates when writing tests or creating test files. Enforces external service mocking (no real API calls), async/await patterns, test independence, and proper use of pytest-asyncio to prevent CI failures and API costs.

Test Writer

Purpose

Guide test creation following Polibase testing standards with proper mocking, async/await patterns, and independence from external services.

When to Activate

This skill activates automatically when:

  • Writing new tests
  • Creating test files in tests/ directory
  • User mentions "test", "pytest", or "testing"
  • Reviewing existing test code

⚡ TDD Workflow (Test-First Development)

ALWAYS write tests BEFORE implementation!

Red-Green-Refactor Cycle

  1. ðŸ”ī Red: Write a failing test

    # Write test first - it will fail (no implementation yet)
    @pytest.mark.asyncio
    async def test_create_politician_saves_to_repository():
        mock_repo = AsyncMock(spec=IPoliticianRepository)
        mock_repo.create.return_value = Politician(id=1, name="åąąį”°åĪŠéƒŽ")
    
        usecase = CreatePoliticianUseCase(mock_repo)
        result = await usecase.execute(CreatePoliticianInputDTO(name="åąąį”°åĪŠéƒŽ"))
    
        mock_repo.create.assert_awaited_once()
    
  2. ðŸŸĒ Green: Write minimal code to pass

    # Now implement just enough to make test pass
    class CreatePoliticianUseCase:
        async def execute(self, input_dto):
            politician = Politician(name=input_dto.name)
            await self.repository.create(politician)
    
  3. â™ŧïļ Refactor: Improve code while keeping tests green

    # Refactor with confidence - tests verify behavior
    class CreatePoliticianUseCase:
        async def execute(self, input_dto):
            # Add validation
            if not input_dto.name:
                raise ValueError("Name required")
            # Extract to method
            politician = self._create_entity(input_dto)
            return await self.repository.create(politician)
    

TDD Benefits

  • ✅ Forces you to think about API design before implementation
  • ✅ Tests serve as documentation
  • ✅ Refactoring is safe (tests catch regressions)
  • ✅ Code is naturally testable (designed for testing)

Remember: If you write implementation first, you're not doing TDD!

ðŸšŦ CRITICAL: Never Call External Services

ABSOLUTELY FORBIDDEN in tests:

  • ❌ Real API calls to Google Gemini or any LLM
  • ❌ Actual HTTP requests to external websites
  • ❌ Real database connections (except integration tests)
  • ❌ File system operations outside temp directories
  • ❌ Network connections of any kind

Why?

  • Tests must run in CI/CD without API keys
  • Tests must be fast (< 1 second per test)
  • Tests must be deterministic (same result every time)
  • Tests must not incur API costs

Quick Checklist

Before committing tests:

  • No External Calls: All external services mocked
  • Fast Execution: Each test runs in < 1 second
  • Isolated: Tests don't depend on each other
  • Deterministic: Same result every time
  • Clear Names: Test name describes what it tests
  • Arrange-Act-Assert: Clear test structure
  • Async Properly: Uses @pytest.mark.asyncio and AsyncMock
  • Mock Verification: Asserts mock calls when relevant
  • Type Hints: Complete type annotations

Test Structure

tests/
├── unit/              # Fast, isolated tests
│   ├── domain/       # Domain entities and services
│   ├── application/  # Use cases (with mocks)
│   └── infrastructure/  # External services (with mocks)
├── integration/       # Tests with real database
├── evaluation/       # LLM evaluation (manual only, not in CI)
└── conftest.py       # Shared fixtures

Core Testing Patterns

1. Mocking External Services

Always use AsyncMock with spec= parameter:

from unittest.mock import AsyncMock

@pytest.fixture
def mock_llm_service():
    # ALWAYS use spec= to catch typos and wrong method calls
    mock = AsyncMock(spec=ILLMService)
    mock.generate_text.return_value = "Mocked response"
    return mock

⚠ïļ Why spec= is CRITICAL:

# ❌ WITHOUT spec= - typos go undetected
mock = AsyncMock()
await mock.genrate_text("prompt")  # Typo! Test still passes!

# ✅ WITH spec= - typos caught immediately
mock = AsyncMock(spec=ILLMService)
await mock.genrate_text("prompt")  # AttributeError!

Use AsyncMock for async methods, never MagicMock:

# ❌ WRONG - MagicMock for async function
mock_repo = MagicMock(spec=IPoliticianRepository)
result = await mock_repo.create(politician)  # Error!

# ✅ CORRECT - AsyncMock for async function
mock_repo = AsyncMock(spec=IPoliticianRepository)
result = await mock_repo.create(politician)  # Works!

2. Async Tests

Use pytest-asyncio:

@pytest.mark.asyncio
async def test_async_function(mock_repo):
    result = await usecase.execute(input_dto)
    assert result.success

3. Test Independence

Each test is self-contained:

def test_create_politician(mock_repo):
    # Setup mock
    mock_repo.save.return_value = Politician(id=1, name="Test")

    # Execute
    result = usecase.execute(input_dto)

    # Assert
    assert result.success

Templates

Use templates in templates/ directory for:

  • Domain service tests
  • Use case tests with mocks
  • Repository integration tests
  • External service tests with mocks

Detailed Reference

For comprehensive testing patterns, mocking strategies, and best practices, see reference.md.

Examples

See examples.md for concrete test examples at each layer.

Running Tests

# Run all tests
docker compose -f docker/docker-compose.yml [-f docker/docker-compose.override.yml] exec polibase uv run pytest

# Run specific test file
docker compose -f docker/docker-compose.yml [-f docker/docker-compose.override.yml] exec polibase uv run pytest tests/unit/domain/test_speaker_domain_service.py

# Run with coverage
docker compose -f docker/docker-compose.yml [-f docker/docker-compose.override.yml] exec polibase uv run pytest --cov=src

# Run only unit tests
docker compose -f docker/docker-compose.yml [-f docker/docker-compose.override.yml] exec polibase uv run pytest tests/unit/

Common Anti-Patterns

  1. ❌ Real API Calls: Most common mistake!
  2. ❌ Testing Implementation Details: Test public interfaces
  3. ❌ Test Dependencies: Each test must be independent
  4. ❌ Missing Async/Await: Forget @pytest.mark.asyncio
  5. ❌ No Mock Verification: Don't check if mocks were called

See reference.md for detailed explanations and fixes.