Marketplace

test-sync

Detect orphaned tests, obsolete assertions, and test-code misalignment. Use for test suite maintenance, cleanup, and traceability validation.

$ インストール

git clone https://github.com/jmagly/ai-writing-guide /tmp/ai-writing-guide && cp -r /tmp/ai-writing-guide/agentic/code/addons/testing-quality/skills/test-sync ~/.claude/skills/ai-writing-guide

// tip: Run this command in your terminal to install the skill


name: test-sync description: Detect orphaned tests, obsolete assertions, and test-code misalignment. Use for test suite maintenance, cleanup, and traceability validation. version: 1.0.0

Test Sync Skill

Purpose

Maintain alignment between test files and source code. Detect orphaned tests (code deleted but tests remain), missing tests, and implementation-coupled tests. Based on UTRefactor research showing automated test maintenance can achieve 89% smell reduction.

Research Foundation

ConceptSourceReference
Test RefactoringUTRefactor (ACM 2024)89% smell reduction
Test SmellsMeszaros (2007)"xUnit Test Patterns"
Test-Code TraceabilityIEEE TSETest maintenance research

When This Skill Applies

  • After major refactoring
  • During test suite health audits
  • When tests fail for deleted code
  • Before releases (cleanup validation)
  • When test count seems disconnected from codebase

Trigger Phrases

Natural LanguageAction
"Find orphaned tests"Detect tests for deleted code
"Sync tests with code"Full alignment analysis
"Are my tests up to date?"Test-code sync check
"Clean up test suite"Find removable tests
"Test coverage gaps"Find missing tests

Sync Analysis Types

1. Orphaned Test Detection

Tests that reference deleted or renamed code:

def find_orphaned_tests(project_dir):
    """Find tests for code that no longer exists"""
    orphans = []

    for test_file in glob(f"{project_dir}/test/**/*.test.ts"):
        # Extract tested module from import/path
        tested_module = infer_tested_module(test_file)

        if not exists(tested_module):
            orphans.append({
                "test_file": test_file,
                "expected_source": tested_module,
                "status": "source_deleted"
            })

        # Check for unused test helpers
        for helper in extract_test_helpers(test_file):
            if not is_used_in_assertions(test_file, helper):
                orphans.append({
                    "test_file": test_file,
                    "item": helper,
                    "status": "unused_helper"
                })

    return orphans

2. Missing Test Detection

Source files without corresponding tests:

def find_missing_tests(project_dir):
    """Find source files without tests"""
    missing = []

    for src_file in glob(f"{project_dir}/src/**/*.ts"):
        if is_testable(src_file):  # Exclude types, index files
            test_file = get_test_path(src_file)
            if not exists(test_file):
                missing.append({
                    "source": src_file,
                    "expected_test": test_file,
                    "functions": extract_public_functions(src_file),
                    "priority": assess_priority(src_file)
                })

    return missing

3. Implementation-Coupled Test Detection

Tests that test implementation details rather than behavior:

COUPLING_PATTERNS = [
    # Testing private methods
    (r'\.\_\w+\(', "Tests private method"),

    # Testing internal state
    (r'\.__\w+', "Accesses internal state"),

    # Mocking too deeply
    (r'mock.*mock.*mock', "Over-mocking"),

    # Testing exact implementation
    (r'toHaveBeenCalledWith.*\{.*\{', "Assertion on implementation details"),
]

def find_coupled_tests(test_file):
    """Detect implementation-coupled tests"""
    content = read_file(test_file)
    issues = []

    for pattern, description in COUPLING_PATTERNS:
        matches = re.findall(pattern, content)
        if matches:
            issues.append({
                "pattern": pattern,
                "description": description,
                "count": len(matches),
                "risk": "Tests may break on safe refactors"
            })

    return issues

4. Test-Code Mapping

Verify traceability between tests and source:

def build_test_map(project_dir):
    """Build mapping of tests to source files"""
    mapping = {}

    for test_file in glob(f"{project_dir}/test/**/*.test.ts"):
        source_file = infer_source(test_file)
        imports = extract_imports(test_file)

        mapping[test_file] = {
            "inferred_source": source_file,
            "actual_imports": imports,
            "coverage": get_coverage_for(test_file),
            "alignment": "aligned" if source_file in imports else "misaligned"
        }

    return mapping

Output Format

## Test Sync Report

**Project**: my-project
**Analysis Date**: 2024-12-12
**Test Files**: 45
**Source Files**: 78

### Summary

| Category | Count | Action |
|----------|-------|--------|
| Orphaned tests | 3 | Delete |
| Missing tests | 8 | Create |
| Implementation-coupled | 5 | Refactor |
| Aligned | 37 | None |

### Orphaned Tests (Safe to Delete)

#### 1. `test/auth/legacy-login.test.ts`
**Status**: Source deleted
**Original Source**: `src/auth/legacy-login.ts` (deleted in commit abc123)
**Last Modified**: 45 days ago
**Action**: DELETE

```bash
rm test/auth/legacy-login.test.ts

2. test/utils/string-helpers.test.ts

Status: Function removed Details: Tests formatCurrency() which was removed Action: DELETE specific test, keep file

// Remove this test block:
describe('formatCurrency', () => { ... });

Missing Tests (Should Create)

1. src/payment/processor.ts (HIGH PRIORITY)

Reason: Payment processing - critical path Public Functions:

  • processPayment(amount, method) - No test
  • refundPayment(transactionId) - No test
  • validateCard(cardInfo) - No test

Suggested Test File: test/payment/processor.test.ts

// Scaffold
describe('PaymentProcessor', () => {
  describe('processPayment', () => {
    it('should process valid payment');
    it('should reject insufficient funds');
    it('should handle network errors');
  });

  describe('refundPayment', () => {
    it('should refund valid transaction');
    it('should reject invalid transaction');
  });
});

Implementation-Coupled Tests (Refactor)

1. test/api/user-service.test.ts:45

Issue: Tests private method _validateEmail Risk: Will break on internal refactoring Current:

it('should validate email', () => {
  expect(service._validateEmail('test@test.com')).toBe(true);
});

Suggested Fix:

it('should reject user with invalid email', () => {
  expect(() => service.createUser({ email: 'invalid' }))
    .toThrow('Invalid email');
});

Test-Code Mapping

Test FileSource FileStatus
test/auth/login.test.tssrc/auth/login.ts✅ Aligned
test/user/profile.test.tssrc/user/profile.ts✅ Aligned
test/api/old-client.test.ts(deleted)❌ Orphaned
(missing)src/payment/processor.ts⚠️ Missing

Recommendations

  1. Immediate: Delete 3 orphaned test files
  2. This Sprint: Create tests for processor.ts (critical)
  3. Debt Reduction: Refactor 5 implementation-coupled tests
  4. Ongoing: Add test-sync to CI pipeline

CI Integration

Add to pre-commit or CI:

- name: Test Sync Check
  run: |
    npx test-sync --project . --strict
    # Fails if orphaned tests or missing critical tests

## Cleanup Actions

### Safe Deletions (Automated)

```bash
# Delete orphaned test files
rm test/auth/legacy-login.test.ts
rm test/utils/old-helpers.test.ts

# Remove orphaned test blocks
sed -i '/describe.*formatCurrency/,/^});$/d' test/utils/string.test.ts

Manual Review Required

  • Tests for code moved to different module
  • Tests that may cover shared utilities
  • Tests with unclear naming

Integration Points

  • Works with /check-traceability command
  • Reports to Test Architect
  • Feeds into test health metrics
  • Part of /project-health-check

Script Reference

test_sync.py

Run sync analysis:

python scripts/test_sync.py --project . --output report.md

cleanup_orphans.py

Remove orphaned tests:

python scripts/cleanup_orphans.py --project . --dry-run

Repository

jmagly
jmagly
Author
jmagly/ai-writing-guide/agentic/code/addons/testing-quality/skills/test-sync
51
Stars
4
Forks
Updated6d ago
Added1w ago