原始内容
Unit Test Skills
A collection of AI agent skills for generating high-quality unit tests. These skills encode battle-tested testing principles that work across any programming language, with additional specialized rules for Java.
Installation
Option 1: Using openskills (Recommended)
openskills automatically generates AGENTS.md for maximum AI agent effectiveness.
# Install skills
npx openskills install clear-solutions/unit-tests-skills
# Auto-generate/update AGENTS.md with installed skills
npx openskills sync
Why openskills? According to Vercel's research, skills alone trigger only 53% of the time. With AGENTS.md, success rate jumps to 100%.
Option 2: Using npx skills
npx skills add clear-solutions/unit-tests-skills
Or install specific skills:
npx skills add clear-solutions/unit-tests-skills --skill generate-test-cases
npx skills add clear-solutions/unit-tests-skills --skill generate-tests
For Claude Code specifically:
npx skills add clear-solutions/unit-tests-skills -a claude-code
Important: After installing with npx skills, manually add the snippet from templates/AGENTS-SNIPPET.md to your project's AGENTS.md file.
Why AGENTS.md Matters
| Configuration | Success Rate |
|---|---|
| Skills alone | 53% |
| Skills + prompting | 79% |
| AGENTS.md | 100% |
AGENTS.md provides persistent context to AI agents on every turn, without requiring them to decide to load skills first. See the full article for details.
Available Skills
| Skill | Command | Description |
|---|---|---|
| Generate Tests | /generate-tests <target> |
Full workflow: analyzes code, outputs test cases for review, then generates test code. Supports Java (JUnit 5, Mockito, AssertJ). |
| Generate Test Cases | /generate-test-cases <target> |
Analysis only: outputs a structured list of test cases in Given-When-Then format without generating code. |
Usage
Generate Tests (Primary Skill)
/generate-tests src/services/OrderService.java
This single command handles the full workflow:
- Analyzes the source code and outputs a structured list of test cases
- Asks you to review the test cases before proceeding
- Generates the actual test files
- Verifies compilation
Analyze Test Coverage Only
If you only want to see what test cases are needed without generating code:
/generate-test-cases src/services/OrderService.java
Testing Principles
These skills enforce proven testing practices:
General Rules (All Languages)
| Rule | Description |
|---|---|
| Test Case Strategy | Strict INCLUDE/EXCLUDE criteria - test each code branch, not collection sizes |
| Naming Conventions | {method}_{state}_{outcome} format for clarity |
| Given-When-Then | Clear structure with actual/expected prefixes |
| Keep Tests Focused | One scenario per test, single responsibility |
| Test Behaviors | Test what it does, not how it's implemented |
| No Logic in Tests | KISS > DRY - use literal values, avoid calculations |
| Clean Test Data | Use helpers and builders, never rely on defaults |
| Cause-Effect Clarity | Setup belongs in the test, not in distant @BeforeEach |
| Public APIs First | Test through public interfaces, not private methods |
| Verify Relevant Args | Use any() for irrelevant arguments in mocks |
Language-Specific Rules
Java
- JUnit 5 + Mockito + AssertJ
@ExtendWith(MockitoExtension.class)for unit tests- FORBIDDEN:
@SpringBootTestin unit tests - Use
ArgumentCaptorinstead ofany()for DTOs - Explicit JSON literals (no
objectMapper.writeValueAsString()) OutputCaptureExtensionfor log verification
Project Structure
skills/
├── generate-test-cases/
│ ├── SKILL.md
│ └── rules/general/
└── generate-tests/
├── SKILL.md
└── rules/tests/
├── general/
├── java/unit/
└── post-generation/
Test Case Generation Strategy
INCLUDE
- Each distinct code branch and outcome
- Each unique return value or exception
- Separate cases for HTTP 400, 401, 403 (never merge)
- Negative test cases for validation constraints
- All paths through private methods (via public API)
EXCLUDE
- Duplicate scenarios with same observable result
- Collection size variations (1, 2, 3 items) unless code has explicit size logic
- Speculative cases (exotic Unicode, massive payloads) unless explicitly handled
- Null arguments unless parameter is
@Nullable - Multiple tests for same exception type
Example Output
Test Cases
## Test Cases for OrderService.calculateTotal
### 1. calculateTotal_validProducts_returnsSum
- **Given:** List with products priced at 50.0 and 100.0
- **When:** calculateTotal() is called
- **Then:** Returns 150.0
- **Code branch:** Happy path
### 2. calculateTotal_emptyList_throwsIllegalArgumentException
- **Given:** Empty product list
- **When:** calculateTotal() is called
- **Then:** Throws IllegalArgumentException
- **Code branch:** Validation - empty input
Generated Test
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock
private ProductRepository productRepository;
@InjectMocks
private OrderService orderService;
@Test
void calculateTotal_validProducts_returnsSum() {
// Given
var product1 = new Product("A", 50.0);
var product2 = new Product("B", 100.0);
when(productRepository.findAll()).thenReturn(List.of(product1, product2));
// When
double actualTotal = orderService.calculateTotal();
// Then
double expectedTotal = 150.0;
assertThat(actualTotal).isEqualTo(expectedTotal);
}
}
Contributing
Contributions are welcome via Pull Requests. All PRs require review and approval from maintainers before merging.
When adding new rules:
- Place general rules in
skills/{skill-name}/rules/general/(orrules/tests/general/for generate-tests) - Place language-specific rules in
skills/generate-tests/rules/tests/{language}/unit/ - Update skill files if new rules need explicit reference
- Ensure your changes follow the existing format and style
Repository Protection
This repository uses branch protection rules:
- Direct pushes to
mainare disabled - All changes require a Pull Request
- PRs require at least one approval from CODEOWNERS
- Status checks must pass before merging
Google's unit tests best practices
Legend: Implemented = rule file exists in skills | Not implemented = no rule file yet Priority: HIGH / MEDIUM / LOW — based on impact on unit test quality
- Tech on the Toilet: Driving Software Excellence, One Bathroom Break at a Time - Dec 2024 (announcement of continuation)
- Increase Test Fidelity By Avoiding Mocks - Feb 2024 — NOT IMPLEMENTED (HIGH) — real > fake > mock hierarchy
- Testing on the Toilet: Separation of Concerns? That's a Wrap! - Dec 2020 — NOT IMPLEMENTED (MEDIUM) — wrap third-party APIs for testability
- Testing on the Toilet: Testing UI Logic? Follow the User! - Oct 2020 — NOT IMPLEMENTED (LOW) — UI-specific, relevant for frontend rules
- Testing on the Toilet: Don't Mock Types You Don't Own - Jul 2020 — NOT IMPLEMENTED (HIGH) — never mock third-party types
- Testing on the Toilet: Tests Too DRY? Make Them DAMP! - Dec 2019 — PARTIALLY IMPLEMENTED (LOW) — DAMP principle not explicit, covered partly by
no-logic-in-tests.md - Testing on the Toilet: Exercise Service Call Contracts in Tests - Nov 2018 — NOT IMPLEMENTED (MEDIUM) — prefer fakes/hermetic servers over mocking services
- Testing on the Toilet: Only Verify Relevant Method Arguments - Jun 2018 — IMPLEMENTED —
verify-relevant-arguments-only.md - Testing on the Toilet: Keep Tests Focused - Jun 2018 — IMPLEMENTED —
keep-tests-focused.md - Testing on the Toilet: Cleanly Create Test Data - Feb 2018 — IMPLEMENTED —
cleanly-create-test-data.md - Testing on the Toilet: Only Verify State-Changing Method Calls - Dec 2017 — NOT IMPLEMENTED (HIGH) — don't verify query/getter methods
- Testing on the Toilet: Keep Cause and Effect Clear - Jan 2017 — IMPLEMENTED —
keep-cause-effect-clear.md - Testing on the Toilet: What Makes a Good End-to-End Test? - Sep 2016 — PARTIALLY IMPLEMENTED —
what-makes-good-test.md(CCCR framework adapted from E2E post; fidelity and precision properties are not covered) - Testing on the Toilet: Change-Detector Tests Considered Harmful - Jan 2015 — NOT IMPLEMENTED (HIGH) — avoid tests that mirror production code
- Testing on the Toilet: Prefer Testing Public APIs Over Implementation-Detail Classes - Jan 2015 — IMPLEMENTED —
prefer-public-apis.md - Testing on the Toilet: Writing Descriptive Test Names - Oct 2014 — IMPLEMENTED —
naming-conventions.md - Testing on the Toilet: Don't Put Logic in Tests - Jul 2014 — IMPLEMENTED —
no-logic-in-tests.md - Testing on the Toilet: Risk-Driven Testing - May 2014 — NOT IMPLEMENTED (LOW) — risk-based test prioritization
- Testing on the Toilet: Effective Testing - May 2014 — PARTIALLY IMPLEMENTED (LOW) — fidelity + precision missing from CCCR framework in
what-makes-good-test.md - Testing on the Toilet: Test Behaviors, Not Methods - Apr 2014 — IMPLEMENTED —
test-behaviors-not-methods.md - Testing on the Toilet: Test Behavior, Not Implementation - Aug 2013 — IMPLEMENTED —
test-behaviors-not-methods.md,general-principles.md - Testing on the Toilet: Know Your Test Doubles - Jul 2013 — NOT IMPLEMENTED (HIGH) — stub vs mock vs fake distinctions
- Testing on the Toilet: Fake Your Way to Better Tests - Jun 2013 — NOT IMPLEMENTED (HIGH) — prefer fakes, fake at lowest layer
- Testing on the Toilet: Don't Overuse Mocks - May 2013 — NOT IMPLEMENTED (HIGH) — limit to 1-2 mocks per test
- Testing on the Toilet: Testing State vs. Testing Interactions - Mar 2013 — NOT IMPLEMENTED (HIGH) — prefer state testing over verify()
- TotT: Making a Perfect Matcher - Oct 2009
- TotT: Finding Data Races in C++ - Nov 2008
- TotT: Contain Your Environment - Oct 2008
- TotT: Floating-Point Comparison - Oct 2008
- TotT: Simulating Time in jsUnit Tests - Oct 2008
- TotT: Data Driven Traps! - Sep 2008
- TotT: Sleeping != Synchronization - Aug 2008
- TotT: 100 and counting - Aug 2008
- TotT: A Matter of Black and White - Aug 2008
- TotT: Testing Against Interfaces - Jul 2008
- TotT: EXPECT vs. ASSERT - Jul 2008
- TotT: Defeat "Static Cling" - Jun 2008 — NOT IMPLEMENTED (MEDIUM) — wrap statics behind injectable interfaces
- TotT: Friends You Can Depend On - Jun 2008
- TotT: The Invisible Branch - May 2008
- TotT: Using Dependency Injection to Avoid Singletons - May 2008 — NOT IMPLEMENTED (MEDIUM) — constructor injection for testability
- TotT: Testable Contracts Make Exceptional Neighbors - May 2008
- TotT: Avoiding Flakey Tests - Apr 2008 — NOT IMPLEMENTED (LOW) — resource isolation between tests
- TotT: Time is Random - Apr 2008
- TotT: Understanding Your Coverage Data - Mar 2008
- TotT: TestNG on the Toilet - Mar 2008
- TotT: The Stroop Effect - Feb 2008
- TotT: Too Many Tests - Feb 2008
- TotT: Refactoring Tests in the Red - Apr 2007
- TotT: Stubs Speed up Your Unit Tests - Apr 2007
- TotT: Extracting Methods to Simplify Testing - Jun 2007