test-organize-layers

📁 dawiddutoit/custom-claude 📅 Jan 26, 2026
4
总安装量
4
周安装量
#52199
全站排名
安装命令
npx skills add https://github.com/dawiddutoit/custom-claude --skill test-organize-layers

Agent 安装分布

mcpjam 4
neovate 4
gemini-cli 4
antigravity 4
windsurf 4
zencoder 4

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

Supporting Resources

Utility Scripts

Quick Start

Creating a new test? Ask yourself:

  1. Do I mock ALL external dependencies? → Unit test (tests/unit/)
  2. Do I use REAL infrastructure (DB/filesystem) but mock external APIs? → Integration test (tests/integration/)
  3. 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 object
  • temp_dir – Temporary directory
  • mock_neo4j_rag – Mocked Neo4jRAG
  • mock_repository_monitor – Mocked monitor

Integration Test Fixtures (function scope, real resources):

  • real_settings – Settings from environment
  • neo4j_database – Real Neo4jDatabase instance
  • neo4j_driver – Real Neo4j driver
  • test_database – Database name with cleanup

E2E Test Fixtures (session/function scope, full stack):

  • indexed_real_codebase – Session-level codebase indexing
  • search_handler – Real SearchCodeHandler
  • neo4j_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.unit marker

Integration Tests (20% of tests):

  • Medium speed (<500ms per test)
  • Real infrastructure, mocked external services
  • Test component interactions
  • Use @pytest.mark.integration marker

E2E Tests (10% of tests):

  • Slow (1-10s per test)
  • Full system integration
  • Test user workflows
  • Use @pytest.mark.e2e marker

Step 5: Validate Test Placement

Check test placement against patterns:

Red Flags (Wrong Layer):

  • ❌ Unit test with neo4j_database fixture → 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_settings and neo4j_database
  • ✅ E2E test with search_handler and indexed_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