test-design-quality

Guides test design to avoid fragility and mock overuse in unit tests.

Updated Jun 24, 2026
One-click install
npx skills add https://github.com/Hakkadaikon/hymme --skill test-design-quality-hakkadaikon
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: test-design-quality
Source: https://github.com/Hakkadaikon/hymme/tree/main/skills/test-design-quality
Command: npx skills add https://github.com/Hakkadaikon/hymme --skill test-design-quality-hakkadaikon

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Tests that break on every refactor and mocks that couple tests to internal implementation details erode trust in the test suite. This Skill provides design norms, based on Vladimir Khorikov's unit testing principles, for writing robust tests that verify observable behavior instead of implementation details. ## Core Features & Use Cases - Fragility Avoidance: Step-by-step procedure to move assertions from implementation details (call counts, call order, private methods) to observable behavior (final output, persisted state), with grep-based completion checks. - Mock Overuse Avoidance: A three-way dependency classification (unmanaged out-of-process, managed out-of-process, in-process collaborators) that dictates when mocks, real instances, or fakes are appropriate, and whether to use output-based or state-based verification. - Use Case: Your vitest suite turns red every time you refactor a helper function. Use this Skill to identify assertions coupled to internal call sequences, rewrite them against final outputs, and reclassify each dependency so mocks are reserved for unmanaged out-of-process communication like email sending. ## Quick Start Review my test file and rewrite any fragile assertions that depend on internal call counts or mocked in-process collaborators so they verify observable behavior instead.

Frequently Asked Questions about test-design-quality

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I fix fragile tests that break on every refactor?

Fragile tests break because they assert on implementation details like call counts or private methods. List every assertion, flag ones touching internal call sequences, and rewrite them to verify observable behavior such as final output or persisted state.

When should I use mocks in unit tests?

Use mocks only for unmanaged out-of-process dependencies like email sending, external APIs, or message buses, where the communication itself is observable behavior. For managed dependencies like your own database use real instances, and for in-process collaborators use real objects.

Should I mock my database repository in unit tests?

No. A repository over your own database is a managed out-of-process dependency, so mocking it couples tests to implementation details. Use a real instance, Testcontainers, or an in-memory fake, and verify the final persisted state instead of save calls.

Why does verifying toHaveBeenCalledTimes make tests brittle?

Asserting call counts or order binds the test to internal procedure rather than results. Any internal refactoring that changes how helpers are invoked breaks the test even when behavior is correct, producing false alarms that erode trust in the suite.

What is the difference between state-based and output-based verification?

State-based verification checks final state or return values and suits managed dependencies and in-process objects. Output-based verification checks outgoing communication with toHaveBeenCalledWith and is reserved for unmanaged out-of-process dependencies like email gateways.