test-organize-layers
npx skills add https://github.com/dawiddutoit/custom-claude --skill test-organize-layers
Agent 安装分布
Skill 文档
Organize Test Layers
Purpose
Ensure new tests are placed in the correct test pyramid layer based on dependencies, mocking patterns, and scope. Prevents anti-patterns like unit tests with real databases or e2e tests with excessive mocking.
When to Use
Use this skill when:
- Creating new test files – Determining correct test layer placement
- Deciding test layer – Choosing between unit, integration, or e2e
- Organizing test structure – Structuring test directories by layer
- Determining fixture scope – Deciding function vs session scope fixtures
- Reviewing test architecture – Validating tests are in correct layers
- Refactoring tests – Moving tests to appropriate layers
Trigger phrases:
- “Where should this test go?”
- “Should this be unit or integration test?”
- “Organize test structure”
- “Test layer placement”
- “Test pyramid organization”
Table of Contents
Core Sections
- Purpose – Test layer placement guidance
- When to Use – Scenarios for using this skill
- Quick Start – Fast decision tree for test placement
- Instructions – Step-by-step layer determination
- Step 1: Identify Test Dependencies – Analyze mocking patterns
- Step 2: Determine Fixture Scope – Match fixtures to layers
- Step 3: Choose Directory Structure – Place files correctly
- Step 4: Apply Test Pyramid Guidelines – Follow distribution
- Step 5: Validate Test Placement – Check for anti-patterns
- Examples – Working examples by layer
- Example 1: Unit Test for Service – Pure logic testing
- Example 2: Integration Test for Repository – Real database
- Example 3: E2E Test for Search Workflow – Full stack
- Requirements – pytest-asyncio, Clean Architecture knowledge
- See Also – Related conftest files and skills
Supporting Resources
- references/reference.md – Test pyramid theory and advanced patterns
Utility Scripts
- Analyze Test Pyramid – Analyze test distribution and compare to ideal pyramid ratios
- Move Test – Intelligently move tests between layers with automatic import updates
- Validate Test Placement – Find misplaced tests and suggest corrections
- Organize Tests – Master orchestration script for all test organization utilities
Quick Start
Creating a new test? Ask yourself:
- Do I mock ALL external dependencies? â Unit test (
tests/unit/) - Do I use REAL infrastructure (DB/filesystem) but mock external APIs? â Integration test (
tests/integration/) - Do I test the FULL stack end-to-end with real services? â E2E test (
tests/e2e/)
Instructions
Step 1: Identify Test Dependencies
Analyze what the test needs to run:
- Unit Tests: Mock everything external (database, filesystem, network, time)
- Integration Tests: Real infrastructure (Neo4j, filesystem), mock external APIs (embeddings, LLMs)
- E2E Tests: Real everything, test complete workflows
Pattern Recognition:
# Unit test pattern - Mock objects
from unittest.mock import AsyncMock, Mock
mock_db = Mock(spec=Neo4jDatabase)
# Integration test pattern - Real fixtures
async def test_with_real_db(neo4j_database: Neo4jDatabase):
# E2E test pattern - Full system
async def test_workflow(search_handler, indexed_real_codebase):
Step 2: Determine Fixture Scope
Match fixture scope to test layer:
Unit Test Fixtures (function scope):
mock_config– Mock Settings objecttemp_dir– Temporary directorymock_neo4j_rag– Mocked Neo4jRAGmock_repository_monitor– Mocked monitor
Integration Test Fixtures (function scope, real resources):
real_settings– Settings from environmentneo4j_database– Real Neo4jDatabase instanceneo4j_driver– Real Neo4j drivertest_database– Database name with cleanup
E2E Test Fixtures (session/function scope, full stack):
indexed_real_codebase– Session-level codebase indexingsearch_handler– Real SearchCodeHandlerneo4j_driver– Connected to indexed database
Step 3: Choose Directory Structure
Place test files following Clean Architecture layers:
tests/
âââ unit/ # Mock everything
â âââ conftest.py # Unit test fixtures
â âââ config/ # Domain/config tests
â âââ application/ # Application layer tests
â â âââ services/
â â âââ commands/
â â âââ queries/
â âââ infrastructure/ # Infrastructure tests (mocked)
â âââ core/ # Core logic tests
âââ integration/ # Real infrastructure, mock external APIs
â âââ conftest.py # Integration fixtures
â âââ neo4j/ # Neo4j integration tests
â âââ infrastructure/ # Real infrastructure tests
â âââ clean_architecture/ # Cross-layer integration
âââ e2e/ # Full stack
âââ conftest.py # E2E fixtures
âââ semantic_search/ # Search E2E tests
âââ test_*.py # Workflow tests
Step 4: Apply Test Pyramid Guidelines
Follow test distribution and characteristics:
Unit Tests (70% of tests):
- Fast (<10ms per test)
- No external dependencies
- Test single responsibility
- Use
@pytest.mark.unitmarker
Integration Tests (20% of tests):
- Medium speed (<500ms per test)
- Real infrastructure, mocked external services
- Test component interactions
- Use
@pytest.mark.integrationmarker
E2E Tests (10% of tests):
- Slow (1-10s per test)
- Full system integration
- Test user workflows
- Use
@pytest.mark.e2emarker
Step 5: Validate Test Placement
Check test placement against patterns:
Red Flags (Wrong Layer):
- â Unit test with
neo4j_databasefixture â Should be integration - â Integration test with all mocks â Should be unit
- â E2E test testing single method â Should be unit
- â Unit test with network calls â Should be integration or e2e
Green Flags (Correct Layer):
- â
Unit test with
Mock(spec=ServiceClass) - â
Integration test with
real_settingsandneo4j_database - â
E2E test with
search_handlerandindexed_real_codebase
Examples
Example 1: Unit Test for Service
Scenario: Testing ChunkingService logic without database
# tests/unit/application/services/test_chunking_service.py
from unittest.mock import Mock
import pytest
from project_watch_mcp.application.services.chunking_service import ChunkingService
@pytest.mark.unit
async def test_chunk_size_calculation(mock_config):
"""Test chunk size calculation logic (pure function)."""
service = ChunkingService(settings=mock_config)
# Mock dependencies
content = "def foo():\n pass\n" * 100
# Test logic without external dependencies
chunks = service.calculate_chunks(content)
assert len(chunks) > 0
assert all(chunk.size <= mock_config.chunking.max_chunk_lines for chunk in chunks)
Why Unit: No database, no filesystem, tests pure logic.
Example 2: Integration Test for Repository
Scenario: Testing Neo4jCodeRepository with real database
# tests/integration/infrastructure/neo4j/test_code_repository.py
import pytest
from project_watch_mcp.infrastructure.neo4j.code_repository import Neo4jCodeRepository
@pytest.mark.integration
async def test_store_and_retrieve_chunk(neo4j_database, real_settings):
"""Test chunk persistence in real Neo4j database."""
repository = Neo4jCodeRepository(neo4j_database.driver, real_settings)
# Create test chunk
chunk = Chunk(
chunk_hash="test_hash",
file_path="/test/file.py",
content="test content",
start_line=1,
end_line=5
)
# Test with REAL database
result = await repository.store_chunk(chunk)
assert result.success
# Verify persistence
retrieved = await repository.get_chunk("test_hash")
assert retrieved.data.content == "test content"
Why Integration: Uses real Neo4j database, tests actual persistence.
Example 3: E2E Test for Search Workflow
Scenario: Testing complete semantic search workflow
# tests/e2e/semantic_search/test_semantic_search_methods.py
import pytest
@pytest.mark.e2e
async def test_search_for_methods(search_handler, indexed_real_codebase):
"""Test searching for methods across real indexed codebase."""
query = SearchCodeQuery(
query_text="chunk validation",
project_name="project-watch-mcp",
search_type=SearchType.SEMANTIC,
limit=10
)
# Execute REAL search with REAL embeddings and REAL database
result = await search_handler.handle(query)
assert result.success
assert len(result.data) > 0
# Verify result quality (LLM usability test)
first_result = result.data[0]
assert "file_path" in first_result
assert "content" in first_result
assert first_result["score"] > 0.5
Why E2E: Full stack (indexed codebase, real embeddings, real Neo4j, real search).
Requirements
- pytest with pytest-asyncio installed
- Understand project’s Clean Architecture layers
- Access to conftest.py files in each test layer
- Familiarity with fixture scopes (function, module, session)
See Also
- tests/unit/conftest.py – Unit test fixtures
- tests/integration/conftest.py – Integration fixtures
- tests/e2e/conftest.py – E2E fixtures
- references/reference.md – Test pyramid theory and advanced patterns