test-implement-constructor-validation

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

Agent 安装分布

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

Skill 文档

Implement Constructor Validation Tests

Purpose

Automatically generate comprehensive constructor validation tests for service classes that follow the fail-fast principle. This skill ensures every required parameter has a corresponding test that validates the service raises ValueError when that parameter is None.

When to Use

Use this skill when:

  • Creating tests for new services – Generating constructor validation tests automatically
  • Validating fail-fast principle – Ensuring services validate required parameters
  • Testing constructor validation – Verifying services raise ValueError for None parameters
  • Testing required parameters – Validating each required parameter has proper validation
  • Following TDD workflow – Creating tests before or alongside service implementation
  • Automating test generation – Reducing manual boilerplate for repetitive test patterns

Trigger phrases:

  • “Generate constructor validation tests”
  • “Test service constructor”
  • “Validate fail-fast principle”
  • “Test required parameters”
  • “Create constructor tests”

Quick Start

Simplest usage – generate tests for a new service:

# 1. Identify the service class you need tests for
# 2. Locate or create the test file
# 3. Invoke this skill with the service file path and test file path

The skill will:

  • Extract constructor signature from service class
  • Identify all required parameters
  • Generate one test method per required parameter
  • Include proper fixtures, type ignores, and error message assertions

Table of Contents

Core Sections

Supporting Resources

Utility Scripts

Advanced Topics

Instructions

Step 1: Analyze Service Constructor

Read the service class to extract:

  • Class name (for test naming)
  • Constructor parameters and their types
  • Validation error messages (from if not X: raise ValueError("...") blocks)
  • Dependencies that need mocking

Example Pattern to Look For:

def __init__(
    self,
    settings: Settings,
    indexing_module: IndexingModule,
    extractor_registry: ExtractorRegistry,
):
    if not settings:
        raise ValueError("Settings is required for IndexingOrchestrator")
    if not indexing_module:
        raise ValueError("IndexingModule is required for IndexingOrchestrator")
    # ... more validations

Step 2: Identify Required Test Fixtures

For each constructor parameter:

  • Determine if it needs a mock fixture (services, repositories)
  • Identify the spec type for mocking
  • Check if the service has async methods (use AsyncMock)

Fixture Naming Pattern: mock_{parameter_name}

Step 3: Generate Test Class Structure

Create a dedicated test class for constructor validation:

class Test{ServiceName}Constructor:
    """Test {ServiceName} constructor and initialization."""

    # Fixtures for each dependency
    @pytest.fixture
    def mock_settings(self):
        """Create mock Settings."""
        return MagicMock(spec=Settings)

    # ... more fixtures

    # Success case test
    def test_constructor_initializes_with_valid_dependencies(self, ...):
        """Test that constructor properly initializes with all valid dependencies."""
        # Arrange + Act
        instance = ServiceName(...)

        # Assert
        assert instance.settings is mock_settings
        # ... assert all dependencies

    # Validation tests (one per parameter)
    def test_constructor_fails_when_{param}_is_none(self, ...):
        """Test that constructor raises ValueError when {Param} is None."""
        with pytest.raises(ValueError) as exc_info:
            ServiceName(
                param=None,  # type: ignore
                # ... other valid params
            )

        assert "{Param} is required for {ServiceName}" in str(exc_info.value)

Step 4: Handle Type Ignore Comments

For each None parameter in validation tests:

  • Add # type: ignore comment on same line
  • This suppresses pyright errors for intentionally wrong types
  • Required because we’re testing failure cases

Pattern:

ServiceName(
    settings=None,  # type: ignore
    other_param=mock_other_param,
)

Step 5: Validate Error Messages

Each validation test must assert the specific error message:

assert "{ParamType} is required for {ServiceName}" in str(exc_info.value)

Error Message Pattern from Constructor:

if not settings:
    raise ValueError("Settings is required for IndexingOrchestrator")

Step 6: Organize Test Methods

Method Ordering:

  1. Success case (all valid parameters)
  2. Validation failures (one per parameter, in parameter order)

Fixture Exclusion Pattern: Each validation test excludes the fixture for the parameter being tested:

def test_constructor_fails_when_settings_is_none(
    self,
    # mock_settings EXCLUDED - this is what we're testing
    mock_indexing_module,
    mock_extractor_registry,
):

Examples

Example 1: Simple Service (2 Parameters)

Service Constructor:

class ChunkingService:
    def __init__(self, settings: Settings, tokenizer: Tokenizer):
        if not settings:
            raise ValueError("Settings is required for ChunkingService")
        if not tokenizer:
            raise ValueError("Tokenizer is required for ChunkingService")

        self.settings = settings
        self.tokenizer = tokenizer

Generated Tests:

class TestChunkingServiceConstructor:
    """Test ChunkingService constructor and initialization."""

    @pytest.fixture
    def mock_settings(self):
        """Create mock Settings."""
        return MagicMock(spec=Settings)

    @pytest.fixture
    def mock_tokenizer(self):
        """Create mock Tokenizer."""
        return MagicMock(spec=Tokenizer)

    def test_constructor_initializes_with_valid_dependencies(
        self, mock_settings, mock_tokenizer
    ):
        """Test that constructor properly initializes with all valid dependencies."""
        service = ChunkingService(
            settings=mock_settings,
            tokenizer=mock_tokenizer,
        )

        assert service.settings is mock_settings
        assert service.tokenizer is mock_tokenizer

    def test_constructor_fails_when_settings_is_none(self, mock_tokenizer):
        """Test that constructor raises ValueError when Settings is None."""
        with pytest.raises(ValueError) as exc_info:
            ChunkingService(
                settings=None,  # type: ignore
                tokenizer=mock_tokenizer,
            )

        assert "Settings is required for ChunkingService" in str(exc_info.value)

    def test_constructor_fails_when_tokenizer_is_none(self, mock_settings):
        """Test that constructor raises ValueError when Tokenizer is None."""
        with pytest.raises(ValueError) as exc_info:
            ChunkingService(
                settings=mock_settings,
                tokenizer=None,  # type: ignore
            )

        assert "Tokenizer is required for ChunkingService" in str(exc_info.value)

Example 2: Complex Service (5 Parameters)

For a complex service with 5 parameters, follow the same pattern as Example 1 above. Create a test class with fixtures for each parameter, a success case test, and one validation failure test for each required parameter. See references/reference.md for detailed pattern analysis and edge cases.

Requirements

  • Python 3.11+
  • pytest installed: uv pip install pytest
  • unittest.mock (standard library)
  • Service class must follow fail-fast validation pattern
  • Service must have if not param: raise ValueError(...) blocks

Automation Strategy

This skill is a prime candidate for full automation because:

  1. Highly Repetitive Pattern – 100+ test classes use identical structure
  2. Deterministic Generation – Output is fully determined by input (constructor signature)
  3. Clear Rules – No subjective decisions required
  4. Type Safety – Can validate against service class signature
  5. Error Message Consistency – Standard format: "{Type} is required for {Service}"

Future Enhancement: Create a script that:

  • Accepts service file path as input
  • Parses AST to extract constructor signature
  • Generates complete test class with all fixtures and validation tests
  • Runs pyright to validate generated tests
  • Writes to appropriate test file location

See Also