AGENT SKILL

slopgate-test-extender

Extend Python test suites with parametrization, fixture reuse, and quality enforcement. Use when asked to add tests, extend existing tests, improve test coverage, consolidate duplicate tests, fix test quality issues, or when Slopgate reports untested-production-code, missing test references, or coverage gaps. Triggers on requests like "add tests for X", "extend these tests", "parametrize tests", "consolidate tests", "fix test quality", "improve test coverage", "write tests for this function", "test this module", "behavior tests", "integration tests", "missing tests", "coverage holes", "untested code", or when a hook denies with test-related findings.

License 许可
MIT
最近更新
2026-11-12
Stars
★ 1
Forks
0

01 前言 Front Matter

name
slopgate-test-extender
author
Slopgate
license
MIT
version
1.0.0
metadata
{ "hermes": { "tags": [ "slopgate", "testing", "pytest", "hypothesis", "coverage" ], "related_skills": [ "slopgate-code-hygiene-refactor", "slopgate-hygiene-orchestrator" ] }, "slopgate": { "rule_ids": [ "untested-production-code", "hypothesis-candidate", "test-integrity", "weak-assertion", "loop-to-parametrize" ], "activation": { "avoid": [ "production-only refactor", "broad lint cleanup", "helper ownership discovery" ], "primary": [ "missing tests", "coverage gaps", "parametrization", "property testing", "weak assertions" ] } } }
description
Extend Python test suites with parametrization, fixture reuse, and quality enforcement. Use when asked to add tests, extend existing tests, improve test coverage, consolidate duplicate tests, fix test quality issues, or when Slopgate reports untested-production-code, missing test references, or coverage gaps. Triggers on requests like "add tests for X", "extend these tests", "parametrize tests", "consolidate tests", "fix test quality", "improve test coverage", "write tests for this function", "test this module", "behavior tests", "integration tests", "missing tests", "coverage holes", "untested code", or when a hook denies with test-related findings.
compatibility
claude-code, opencode, codex, hermes, slopgate

02 资源文件 5

03 SKILL.md 正文

Test Extender

Extend pytest test suites by finding existing tests, evaluating parametrization opportunities, reusing fixtures, and enforcing quality standards.

When to Use

Use when the primary work is test coverage, test quality, parametrization, fixtures, or property-based testing.

  • Slopgate reports untested-production-code, hypothesis-candidate, test-integrity, weak assertions, loop-to-parametrize findings, or missing test references.
  • User asks to add tests, extend tests, improve coverage, parametrize examples, or decide between finite examples and Hypothesis.
  • Use alongside production refactor skills only after the production seam is clear.

When Not to Use

Do not use as the primary skill for production-only structure failures. Use slopgate-code-hygiene-refactor first, then return here for coverage.

Do not add Hypothesis just because it sounds stronger: use parametrization for finite named examples and Hypothesis for broad domains/invariants.

Do not use for repo-wide lint orchestration; use slopgate-hygiene-orchestrator.

Workflow

1. Discover Existing Tests

Run analysis script to find tests and identify issues:

python scripts/analyze_tests.py tests/ --json

Or search with ripgrep for specific patterns:

# Find tests for a specific function
rg "def test_.*<function_name>" tests/ -l

# Find parametrized tests
rg "@pytest.mark.parametrize" tests/ -A5

# Find tests with loops (anti-pattern)
rg "for .* in .*:" tests/test_*.py -B2 -A2

Use semantic search via Serena tools:

find_symbol(name_path_pattern="test_*", relative_path="tests/", include_kinds=[12])

2. Discover Fixtures

Run fixture discovery:

python scripts/find_fixtures.py tests/ --with-usage --json

Check conftest hierarchy:

rg "@pytest.fixture" tests/**/conftest.py -A3

3. Evaluate Extension Opportunities

Parametrization candidates:

  • Multiple similar test functions (test_foo_case1, test_foo_case2)
  • Tests with loops or conditionals
  • Tests with 3+ assertions on similar values
  • Finite, explicit edge-case sets (empty, single, max, boundary)

Property-based / Hypothesis candidates:

  • Functions with wide input domains (strings, numbers, collections)
  • Invariants that should hold for ALL inputs (round-trip, idempotency, monotonicity)
  • Complex state machines or parsers where enumerating cases is infeasible
  • Code that processes untrusted/external data
  • When the test would need 10+ parametrized cases to feel confident

Decision rule:

  • Start with parametrization for known edge cases and behavioral examples.
  • Add Hypothesis when the input space is large, the invariant is strong, or the function processes arbitrary data.
  • Both can coexist: parametrize the known-critical cases, use Hypothesis for the general invariant.
  • Do not add Hypothesis as a new project dependency without checking project policy; if it is unavailable and dependency changes are out of scope, write named parametrized examples and leave the property-test recommendation explicit.

Fixture reuse opportunities:

  • Repeated setup code across tests
  • Common object construction patterns
  • Shared test data

Coverage gap candidates (from Slopgate untested-production-code):

  • Public symbols with static_test_reference_coverage=0%
  • Functions/classes with no test references
  • New code written without accompanying tests

4. Implement Extensions

Follow quality rules strictly. See references/quality_rules.md.

Key requirements:

  • No loops or conditionals in test bodies
  • All assertions include descriptive messages
  • No magic values (use constants, fixtures, parametrize)
  • Use pytest.param() with id= for named cases
  • Match naming: test_<unit>_<scenario>_<expected>

Parametrize vs Hypothesis — implementation guidance:

Aspect Parametrize Hypothesis
When Known edge cases, explicit examples Large input space, universal invariants
Import import pytest from hypothesis import given, strategies as st
Decorator @pytest.mark.parametrize("x,y", [...]) @given(st.integers())
Cases Explicit: [(1, 2), (0, 0)] Generated: st.text(), st.lists(st.integers())
Best for Behavior examples, regression cases, boundary values Round-trips, parsers, validators, idempotency
Avoid 10+ hand-written cases for simple invariants When the "property" is just reimplementing the function

Parametrize example:

@pytest.mark.parametrize(
    ("input_val", "expected"),
    [
        pytest.param(1, 2, id="simple_case"),
        pytest.param(0, 0, id="zero_case"),
        pytest.param(-1, -2, id="negative_case"),
    ],
)
def test_double_value(input_val: int, expected: int) -> None:
    result = double(input_val)
    assert result == expected, f"double({input_val}) should be {expected}"

Hypothesis example:

from hypothesis import given, strategies as st

@given(st.lists(st.integers()))
def test_reverse_twice_returns_original(values: list[int]) -> None:
    result = reverse(reverse(values))
    assert result == values, "reversing twice should preserve the original list"

@given(st.text())
def test_serialize_roundtrip(raw: str) -> None:
    """parse(serialize(x)) == x"""
    assert parse(serialize(raw)) == raw, "round-trip should preserve data"

Coexistence pattern:

# Known-critical cases as parametrize
@pytest.mark.parametrize("raw", [
    pytest.param("", id="empty"),
    pytest.param("\x00", id="null_byte"),
    pytest.param("a" * 10000, id="huge_string"),
])
def test_parse_known_cases(raw: str) -> None:
    assert parse(raw) is not None

# General invariant as hypothesis
@given(st.text())
def test_parse_never_crashes(raw: str) -> None:
    result = parse(raw)  # should not raise
    assert isinstance(result, (ParseResult, type(None)))

Responding to untested-production-code findings:

  1. Read the Slopgate output for the unreferenced symbol(s) and the suggested scaffold.
  2. Identify the public behavior users depend on — not just the function signature.
  3. Add behavior/integration tests around the public entrypoint.
  4. Avoid testing every helper directly; prefer observable behavior through the public API.
  5. If the symbol is dead API, consider deleting or private-scoping instead of adding tests.
  6. Verify with pytest <affected_tests> and re-run slopgate lint check.

See references/parametrization_patterns.md for patterns. See references/hypothesis_patterns.md for property-based testing patterns.

5. Validate Quality

make quality

Progress gate: Acknowledge guidelines compliance before proceeding.

Quick Reference

Parametrize Pattern

@pytest.mark.parametrize(
    ("input_val", "expected"),
    [
        pytest.param(1, 2, id="simple_case"),
        pytest.param(0, 0, id="zero_case"),
    ],
)
def test_double_value(input_val: int, expected: int) -> None:
    result = double(input_val)
    assert result == expected, f"double({input_val}) should be {expected}"

Hypothesis Pattern

from hypothesis import given, strategies as st

@given(st.lists(st.integers()))
def test_reverse_twice_returns_original(values: list[int]) -> None:
    result = reverse(reverse(values))
    assert result == values, "reversing twice should preserve the original list"

Coexistence Pattern

# Explicit edge cases via parametrize
@pytest.mark.parametrize("raw", [
    pytest.param("", id="empty"),
    pytest.param("\x00", id="null_byte"),
])
def test_parse_edge_cases(raw: str) -> None:
    assert parse(raw) is not None

# General invariant via hypothesis
@given(st.text())
def test_parse_never_crashes(raw: str) -> None:
    result = parse(raw)  # should not raise
    assert isinstance(result, (ParseResult, type(None)))

Fixture Scopes

Scope When
function Fresh state per test (default)
module Expensive setup, shared in file
session Very expensive, immutable

Test Classification

Tests must verify: function (correctness), behavior (state changes), robustness (error handling), or rigor (boundaries).

Structure-only tests should be absorbed into meaningful tests or removed.

Troubleshooting

Fixture Consolidation with Duplicate-Check Hooks

When hooks block duplicate fixture definitions, follow this order:

Problem: Cannot add fixture to conftest.py because hook detects duplicate with test file.

Solution 1: Use intermediate conftest.py

# If consolidating from tests/grpc/test_foo.py:
# 1. Add fixture to tests/grpc/conftest.py (not tests/conftest.py)
# 2. Remove fixture from tests/grpc/test_foo.py
# 3. Tests inherit from nearest conftest.py in hierarchy

Solution 2: Rename-then-migrate

# In test file, temporarily rename:
@pytest.fixture
def _local_sample_config() -> Config:  # Renamed to avoid conflict
    ...

# Now add to conftest.py with original name
# Then remove _local_sample_config from test file

Key insight: The conftest.py hierarchy allows fixtures in tests/grpc/conftest.py to serve all tests under tests/grpc/ without conflicting with tests/conftest.py.

Loop-to-Parametrize Conversion

When converting loops to parametrization, split into separate test functions if the loop body has multiple assertions:

# Before (anti-pattern):
def test_states() -> None:
    for state in (A, B, C):
        assert state in valid_states
        obj = create(state=state)
        assert obj.should_skip

# After (two parametrized tests):
@pytest.mark.parametrize("state", [pytest.param(A, id="a"), ...])
def test_state_is_valid(state: State) -> None:
    assert state in valid_states, f"{state} should be valid"

@pytest.mark.parametrize("state", [pytest.param(A, id="a"), ...])
def test_state_triggers_skip(state: State) -> None:
    obj = create(state=state)
    assert obj.should_skip, f"{state} should trigger skip"

Resources

  • scripts/analyze_tests.py - Find tests, detect anti-patterns
  • scripts/find_fixtures.py - Discover fixtures, analyze scope/usage
  • references/quality_rules.md - Complete quality rules
  • references/parametrization_patterns.md - Parametrization examples
  • references/hypothesis_patterns.md - Property-based testing examples

04 同仓库更多 Skills

vasceannie
vasceannie/slopgate

type-strictness

Enforce strict type compliance by eliminating `Any` types and `# type: ignore` comments. Use when: (1) Editing code that contains `Any` as a type annotation (2) Code has `# type: ignore` or `# pyright: ignore` comments (3) User requests type fixes or type strictness enforcement (4) Importing from untyped third-party libraries (5) User asks to "fix types", "remove Any", or "add proper typing" (6) Pyrefly or mypy reports type errors that need resolution (7) Code review reveals weak typing patterns Follows hierarchical resolution: codebase inference → type stubs → library inspection → type guards → casting (last resort).

代码审查
★ 1
vasceannie
vasceannie/slopgate

slopgate-test-extender

Extend Python test suites with parametrization, fixture reuse, and quality enforcement. Use when asked to add tests, extend existing tests, improve test coverage, consolidate duplicate tests, fix test quality issues, or when Slopgate reports untested-production-code, missing test references, or coverage gaps. Triggers on requests like "add tests for X", "extend these tests", "parametrize tests", "consolidate tests", "fix test quality", "improve test coverage", "write tests for this function", "test this module", "behavior tests", "integration tests", "missing tests", "coverage holes", "untested code", or when a hook denies with test-related findings.

代码审查测试与质量
★ 1
vasceannie
vasceannie/slopgate

slopgate-intelligent-coding-patterns

Pattern-selection playbook for agents editing code with complex branching, stateful parsers/workflows, duplicated skeletons, policy checks, or ordered transforms. Load before refactoring if/elif dispatch chains, boolean-flag state machines, repeated validation predicates, parallel provider/language implementations, or regex/content transformation pipelines. Also load when asked to "apply a design pattern", "which pattern should I use here", "refactor this switch statement", "replace if-elif chain", "state machine pattern", "strategy pattern", "template method", "pipeline pattern", "specification pattern", "dispatch table", "guard clause refactor", "reduce cyclomatic complexity", or when Slopgate fires PY-CODE-014, PY-CODE-017, PY-CODE-018, QUALITY-LINT-001, or PY-QUALITY-010. Use with behavior-locking tests and avoid pattern theater for simple one-off code.

开发工程师设计师代码审查视觉设计
★ 1
vasceannie
vasceannie/slopgate

slopgate-hygiene-orchestrator

Orchestrate systematic elimination of linter warnings and errors across Python, TypeScript, and Rust codebases. Use when asked to "clean up lints", "fix all warnings", "run hygiene", "eliminate type errors", "orchestrate code quality fixes", "fix lint errors", "resolve quality gate failures", "pass CI checks", "reduce tech debt", "refactor to pass hooks", or when a Slopgate hook denies with QUALITY-LINT-001, PY-CODE-017, PY-CODE-018, or any collector finding. This skill coordinates multiple code-hygiene-enforcer agents working in parallel on non-conflicting file groupings, tracks progress persistently via JSON exports, and loops until all issues are resolved. CRITICAL: Never run linters directly—always use `slopgate lint check` as the primary gate, discover project-specific tools from config files, and export findings to JSON for tracking.

代码审查Skill与智能体开发
★ 1
vasceannie
vasceannie/slopgate

slopgate-code-smell-utility-locator

Autoactivate when code-smell hooks or reviews mention feature envy, thin wrappers, duplicate helpers, duplicate code, scattered helpers, builders/factories/config/constants/dataclass reuse, PY-CODE-012, PY-CODE-013, QUALITY-LINT-001, or repeated slopgate code-quality denials. Also load when asked to "find existing helpers", "consolidate utilities", "search for duplicate code", "where is this already implemented", "reuse existing logic", "don't duplicate this", "find similar functions", "utility inventory", "code smell radar", or before adding new helpers/wrappers so agents can find existing shared utilities and consolidate instead of duplicating.

开发工程师代码审查
★ 1
vasceannie
vasceannie/slopgate

slopgate-code-hygiene-refactor

Recovery playbook for Slopgate and project quality failures. Load after hook/lint denials such as PY-CODE-017 flat sibling modules, PY-CODE-018 oversized modules, QUALITY-LINT-001 post-edit quality backstops, PY-QUALITY-010 magic numbers / repeated literals, PY-CODE-012/PY-CODE-013 smell findings, type-suppression bans, duplicate helpers, or repeated hygiene retry loops. Also load when asked to "refactor this module", "split this file", "extract a class", "reduce complexity", "fix god class", "flatten module hierarchy", "move code to a package", "extract helpers", "consolidate duplicates", "replace magic numbers with constants", or when a hook blocks an edit with structural complaints. Focuses on preserving public APIs while refactoring toward packages, cohesive modules, typed seams, and focused tests.

开发工程师代码审查
★ 1