workflows/workflows/agent-environment-setup/platforms/codex/skills/unit-testing/SKILL.md
Unit testing best practices covering test design, mocking strategies, coverage analysis, TDD workflow, and assertion patterns. Use when writing, reviewing, or improving unit tests.
npx skillsauth add cubetiq/cubis-foundry unit-testingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Provide a rigorous, repeatable methodology for designing, writing, and maintaining unit tests that maximize defect detection while minimizing maintenance cost. This skill ensures every unit test is fast, isolated, deterministic, and focused on a single behavior.
Identify the unit under test -- Select a single function, method, or class. Focusing on one unit at a time prevents coupling between tests and makes failures easy to diagnose.
Define the behavioral contract -- Write down the expected inputs, outputs, side effects, and error conditions before writing any test code. This ensures tests validate behavior, not implementation details.
Apply the Arrange-Act-Assert pattern -- Structure every test into setup (Arrange), invocation (Act), and verification (Assert). Consistent structure makes tests scannable and reduces cognitive load during review.
Name tests with the GIVEN-WHEN-THEN convention -- Use descriptive names like shouldReturnEmptyList_whenNoItemsExist. Clear names serve as living documentation and speed up failure diagnosis.
Mock only direct collaborators -- Replace external dependencies (databases, HTTP clients, file systems) with test doubles. Mocking deeper layers creates brittle tests that break on internal refactors.
Prefer stubs over mocks when possible -- Use stubs to provide canned answers and mocks only when verifying interaction is the goal. Over-mocking couples tests to implementation details and makes refactoring painful.
Write the failing test first (Red) -- In TDD, write a test that fails for the right reason before writing production code. This proves the test actually exercises the intended behavior.
Implement the minimum code to pass (Green) -- Write only enough production code to make the failing test pass. Minimal implementation prevents speculative design and keeps the feedback loop tight.
Refactor with confidence (Refactor) -- Clean up duplication and improve naming while all tests remain green. The passing suite acts as a safety net, allowing bold structural changes.
Test edge cases and error paths -- Include boundary values, null inputs, empty collections, and exception scenarios. Edge cases account for a disproportionate share of production bugs.
Assert one logical concept per test -- Each test should verify a single behavior or outcome. Multiple unrelated assertions in one test obscure which behavior actually failed.
Keep tests deterministic and independent -- Avoid shared mutable state, random data without seeds, and ordering dependencies. Non-deterministic tests erode team trust in the suite.
Measure coverage as a diagnostic, not a target -- Use line, branch, and mutation coverage to find untested paths. Chasing a coverage number without quality assertions creates false confidence.
Maintain test speed below 100ms per test -- Fast tests encourage frequent execution. When a test is slow, identify the bottleneck (usually I/O) and replace it with a test double.
Review tests with the same rigor as production code -- Apply naming, structure, and readability standards to tests. Poorly written tests become maintenance liabilities that teams abandon.
Refactor tests when they become brittle -- If many tests break after a small production change, the tests are over-coupled. Extract shared fixtures, simplify mocks, and align tests to public interfaces.
## Unit Test Plan
### Unit Under Test
- **Module:** <module path>
- **Function/Class:** <name>
- **Behavioral Contract:** <expected behavior summary>
### Test Cases
| # | Test Name | Arrange | Act | Assert | Edge Case? |
|---|-----------|---------|-----|--------|------------|
| 1 | ... | ... | ... | ... | Yes/No |
### Mocking Strategy
| Dependency | Double Type | Rationale |
|------------|-------------|-----------|
| ... | Stub/Mock/Fake | ... |
### Coverage Targets
| Metric | Current | Target | Gap Analysis |
|----------|---------|--------|--------------|
| Line | ... | ... | ... |
| Branch | ... | ... | ... |
| Mutation | ... | ... | ... |
| Topic | File | Load When |
|--------------------|-------------------------------------|-------------------------------------------------|
| Test Design | references/test-design.md | Designing test structure and naming conventions |
| Mocking Strategies | references/mocking.md | Choosing between stubs, mocks, fakes, spies |
| Coverage Analysis | references/coverage.md | Interpreting and improving coverage metrics |
| TDD Workflow | references/tdd-workflow.md | Practicing red-green-refactor cycle |
| Assertion Patterns | references/assertion-patterns.md | Writing precise, readable assertions |
tools
Use when investigating latest vendor behavior, comparing tools or platforms, verifying claims beyond the repo, or gathering external evidence before implementation.
documentation
Use when designing database schemas, normalization strategies, indexing plans, query optimization, and migration workflows for relational, document, or hybrid data stores.
development
Use when writing, reviewing, or refactoring modern C#/.NET code, including minimal APIs, records, async streams, pattern matching, DI lifetimes, and memory-efficient performance tuning.
development
Use when conducting code reviews, building review checklists, calibrating review depth, providing structured feedback, or establishing team review practices. Covers review methodology, feedback patterns, automated checks, and batch review strategies.