behavioral-testing/SKILL.md
Behavioral testing methodology — test what users experience, not how code is structured. Use when writing tests, reviewing test quality, planning test strategy for new features, or when existing tests are brittle/verbose/coupled to implementation details. Triggers: writing tests, TDD, test review, "tests keep breaking", "too many mocks", "tests are verbose", test coverage planning, behavior-driven development.
npx skillsauth add snqb/my-skills behavioral-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.
Test observable behavior. Keep tests terse. Never test implementation details.
1. Test what the user sees, not how the code works
2. If a refactor breaks a test, the test was wrong
3. Mocks isolate — they are never the thing being tested
4. Every assertion must trace to a user-observable outcome
5. Terse tests > thorough ceremony
Arrange: Set up the minimum preconditions
Act: Do the thing the user would do
Assert: Check what the user would see
That's it. No red-green-red ritual. No verbose setup. If test setup is longer than the assertion, something is wrong.
Test behavior at boundaries, not every line of code:
| Always test | Skip | |-------------|------| | What happens with empty/null/whitespace input | Internal method call order | | Error messages users see | Which helper function was called | | State transitions (loading → success → error) | Implementation details of state management | | API failure recovery | Mock call counts (unless it IS the behavior) | | Edge cases users will hit | Happy-path-only coverage |
Name tests after the behavior, not the function:
✅ "shows error when email is empty"
✅ "redirects to login after session expires"
✅ "prevents duplicate submission on double-click"
❌ "test validateEmail"
❌ "test handleSubmit calls api"
❌ "test useAuth hook returns null"
// ✅ Terse — tests one behavior, reads in 3 seconds
test('shows error when email is empty', () => {
render(<LoginForm />);
click(submitButton());
expect(screen.getByText('Email is required')).toBeVisible();
});
// ❌ Verbose — ceremony obscures intent
test('should display an error message when the user submits the form without entering an email address', () => {
const mockOnSubmit = vi.fn();
const mockOnError = vi.fn();
const { container } = render(
<LoginForm onSubmit={mockOnSubmit} onError={mockOnError} />
);
const form = container.querySelector('form');
const button = screen.getByRole('button', { name: /submit/i });
await userEvent.click(button);
expect(mockOnSubmit).not.toHaveBeenCalled();
expect(mockOnError).toHaveBeenCalledWith(expect.objectContaining({ field: 'email' }));
expect(screen.getByText('Email is required')).toBeVisible();
});
The terse test catches the same bug. The verbose test also asserts on mock internals — those assertions break when you refactor, even if behavior is unchanged.
Before writing or reviewing any test, run these checks:
□ Am I asserting on a mock instead of real output?
→ If yes: delete the assertion or unmock it
□ Would a refactor break this test even though behavior hasn't changed?
→ If yes: the test is coupled to implementation — rewrite it
□ Is mock setup > 50% of the test?
→ If yes: use an integration test with real components instead
□ Does this test name describe a user-visible behavior?
→ If no: rename it or question whether it needs to exist
□ Did I write this test after the implementation?
→ If yes: verify it actually fails when behavior is broken, not just when code changes
Mock external boundaries only. Network calls, third-party services, timers — things outside your control.
Never mock internal modules, components you own, or "just to be safe."
If you need to mock a thing to test it, the design has a coupling problem — fix the design, not the test.
Load these only when needed:
documentation
Enrich Markdown articles with inline Wikipedia links. First mention of each notable entity gets a hyperlink. Use when asked to add wiki links, enrich, or add references to .md files.
development
Structured visual QA: screenshot → batch issues → fix all → verify. Replaces the 300-cycle screenshot→edit death spiral. Optional bishkek review as exit gate. Use when building/polishing UI with browser testing, or when user asks for N iterations/reviews.
development
Find complex code, analyze intent, recommend battle-tested library replacements. Uses radon/eslint for detection, GitHub quality search for alternatives.
research
Research real-world UI patterns from curated galleries (Collect UI, Component Gallery, Mobbin). Use when exploring what exists: dropdowns, accordions, inputs, navigation, cards, modals, etc.