test-implement-constructor-validation

Auto-generate constructor validation tests from service class signatures. Use when creating tests for new services, validating fail-fast principle, ensuring constructor validation, or testing required parameters. Analyzes service __init__ methods and generates pytest.raises(ValueError) tests for each required parameter. Works with Python service classes following dependency injection pattern. High automation opportunity (100+ test classes use this pattern).

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "test-implement-constructor-validation" with this command: npx skills add dawiddutoit/custom-claude/dawiddutoit-custom-claude-test-implement-constructor-validation

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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

uv-python-version-management

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

java-best-practices-code-review

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

python-best-practices-async-context-manager

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

textual-widget-development

No summary provided by upstream source.

Repository SourceNeeds Review