Skip to main content

Testing

Testing Custy

Required for Changes

Build confidence from one affected contract to the complete test suite.

Commandpython -m pytest

Category

Developer Guide

Quick Command

python -m pytest [PATH] [OPTIONS]

unitCLIintegrationregressionpre-commit

Overviewโ€‹

Custy's pytest configuration discovers test_*.py, Test* classes, and test_* functions under tests/. The default run enables coverage for app, reports missing lines, uses strict marker and configuration validation, and keeps tracebacks short.


Test Layers

Where a Change Is Exercised

CLI Contracts

Tests under tests/cli cover command wiring, option metadata, dataclass models, resolvers, and application entry points.

Core Behavior

Tests under tests/core cover pipelines, workflows, Git services, changelog processing, version strategies, initialization, backup, and cleanup.

Configuration

Tests under tests/config exercise loading, missing files, invalid TOML, nested access, required values, and CLI-to-config fallback.

Integration

Tests under tests/integration connect resolvers, builders, profiles, and feature flows across module boundaries.

Regression

Tests under tests/regression preserve behavior for previously discovered builder, resolver, configuration, workflow, and pipeline failures.

Shared Infrastructure

tests/fixtures and tests/helpers provide reusable project, Git, filesystem, configuration, CLI, version, changelog, and pipeline support.

Focused Validation

Use a path or node ID that matches the changed contract.

Focused pytest examples
bash
# One file
python -m pytest tests/cli/commands/changelog/test_resolver_changelog.py

# One test class or method

python -m pytest tests/core/pipeline/test_command_resolver.py::TestCommandResolver

# One feature group

python -m pytest tests/core/git_ops/tag_strategy

# One integration flow

python -m pytest tests/integration/test_run_profiles.py

Pipeline tests receive one-time built-in step registration from tests/conftest.py. Individual tests should not repeatedly register the same names because StepRegistry rejects duplicates.


What to Test for Each Extension

Before You Begin

  • CommandRequired

    Cover Typer registration or callback behavior, option metadata, the resolved argument model, configuration precedence, and the delegated core action.

  • Pipeline stepRequired

    Cover the engine call, registration, profile membership, priority, deduplication, ordering, and failure propagation.

  • Version strategyRequired

    Cover defaults, explicit inputs, latest-tag or external-tool behavior, returned tag format, and actionable errors.

  • ConfigurationRequired

    Cover a present value, a missing value, the built-in default, explicit CLI precedence, invalid shape, and the consuming runtime path.

  • Side effectRequired

    Use temporary paths and mocked Git or subprocess boundaries; never depend on a contributor's real repository or credentials.


Pre-Commit Quality Gates

The repository hook configuration uses Ruff for linting and safe lint fixes, Black as the single Python formatter, and utility hooks for trailing whitespace and final newlines. Ruff and Black read their policy from pyproject.toml.

Pre-commit validation
bash
# Validate the hook configuration without running hooks
make pre-commit-validate

# Fast contributor check for staged files

make pre-commit-run-staged

# Broad check for all tracked files

make pre-commit-run

Complete Validation

Full tests and quality checks
bash
# Complete pytest suite with the configured coverage report
python -m pytest

# Repository helper: formatting check, lint, then tests

make check

The lower-level equivalents used by the Make targets are python -m black --check app tests, python -m ruff check app tests, and python -m pytest. Use the repository's active SOURCE_DIRS values when reproducing a Make result rather than assuming a hard-coded list.



Continue