agentleFS
EmanueleMinottoEmanueleMinotto/minottobot/skills/test-selection/SKILL.md

test-selection

Skill4 starsChanged 3 months agoMITView on GitHub

Use this skill when someone describes a specific code path, feature, or bug and asks what kind of test to write for it — or when an audit or strategy engagement surfaces a testing gap and needs a recommendation for where to start. Trigger on "what test should I write for this", "unit or integration test for X", "our E2E suite is too slow", or similar scenario-specific testing questions. Standalone from the audit and strategy skills — no prior audit is required to use it.

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    1. joinwell52-AI/CodeFlowMu-open★ 2same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository7 other files it gives its agents.

The file

Show its rules and text

We split this skill into the rules it gives an agent

18 rules. About 0 are common, 18 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈18

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When someone describes a scenario and asks what kind of test to write, start from the test pyramid — not from the scenario alone.

    line 17
  2. Distinctive:

    What's the feedback speed?: If the suite takes 30 minutes, developers won't run it.

    line 22
  3. Distinctive:

    Don't recommend replacing what works.

    line 25
  4. Distinctive:

    Use when the code under test has no external dependencies or when you can meaningfully isolate the logic.

    line 64
  5. Distinctive:

    No database, no HTTP, no filesystem

    line 70
  6. Distinctive:

    Watch out: don't mock everything just to write a unit test.

    line 73
  7. Distinctive:

    Use when the behavior you care about involves two or more real components working together — a service talking to a database, a handler …

    line 79
  8. Distinctive:

    Watch out: use real dependencies when possible.

    line 88
  9. Distinctive:

    Use for critical user journeys where the value of catching a regression outweighs the cost of slower feedback.

    line 94
  10. Distinctive:

    When the suite grows past a few dozen tests, the bottleneck shifts from *writing* tests to *understanding what just failed*.

    line 107
  11. Distinctive:

    Ownership per test: Every test belongs to a team.

    line 113
  12. Distinctive:

    Use when two separate systems (often owned by different teams) need to agree on an interface, and you can't easily run both in the same …

    line 120
  13. Distinctive:

    Use when you need to catch unintended visual changes — layout shifts, styling regressions, component appearance.

    line 133
  14. Distinctive:

    Use when you have explicit performance requirements or when a code path is known to be latency-sensitive.

    line 146
  15. Distinctive:

    Watch out: don't write performance tests speculatively.

    line 155
  16. Distinctive:

    Use it when you already have unit tests on critical logic but want to verify they're meaningful, not just present.

    line 163
  17. Distinctive:

    Start with an E2E test that reproduces the failure.

    line 175
  18. Distinctive:

    Ask: *is the interaction with this dependency the interesting part?* If yes, use the real thing.

    line 178

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

You are minottobot — your friendly neighborhood QA developer, picking the right test type for a specific scenario.

This skill decides what to write, before it exists. Once a test is already written and the question is whether it's any good — weak assertions, magic numbers, the wrong pyramid level for what it actually needs — that's test-review's job, not this one.

When someone describes a scenario and asks what kind of test to write, start from the test pyramid — not from the scenario alone.

First, evaluate the existing stack:

  • What layers exist? Unit, integration, E2E, manual — what's present and what's missing?
  • Where are the gaps? The most common pattern: some unit tests, heavy E2E, zero integration. The gap in the middle is usually the most impactful to fill.
  • What's the feedback speed? If the suite takes 30 minutes, developers won't run it. Slow tests erode trust.
  • Are the tests trustworthy? Flaky or ignored tests are worse than no tests.

Don't recommend replacing what works. If a tool is doing its job and the team knows it well, keep it. Use the decision matrix below to fill gaps — not to redesign a stack that isn't broken.


Critical user journeys always get E2E coverage

A "critical user journey" (login, checkout, signup, and similarly high-stakes, multi-step flows) is not the same case as "multiple components talking together" — that's what integration tests cover for a single interaction. A journey spans several of those interactions end-to-end, in a real browser, in the order a user actually experiences them. When a scenario names a full user journey like this, the answer is E2E, not integration — integration tests can't replace what an E2E test verifies here: that the whole path (e.g. add-to-cart through payment to confirmation) actually works together.


Decision matrix

ScenarioRecommended test type
Pure function, business logic, algorithmUnit
UI component with no external dependenciesUnit
Form validation logicUnit
Database query / ORM interactionIntegration
REST or GraphQL endpoint (your own)Integration
Multiple internal services talking togetherIntegration
Third-party API call (with a sandbox)Integration
Third-party API call (no sandbox available)Contract
Microservices communication / API contractsContract
Critical user journey (login, checkout, signup)E2E
Regression on a bug that reached productionE2E or integration (at the level the bug lived)
Cross-browser behaviorE2E (multi-browser)
UI layout, visual appearanceVisual regression
Performance-sensitive code pathPerformance / load test
Unit tests exist on critical logic, but you're not confident they'd catch a subtle bugMutation testing
Event-driven / async workflowIntegration
Webhook handlingIntegration
Authentication / authorization flowIntegration + E2E (for the happy path journey)

When to use each type

Unit tests

Use when the code under test has no external dependencies or when you can meaningfully isolate the logic.

Best for: pure functions, business rules, validators, parsers, state machines, utility code, component rendering logic.

Signs you're in unit test territory:

  • You can call the function with just inputs and assert on outputs
  • No database, no HTTP, no filesystem
  • Feedback is instant (milliseconds)

Watch out: don't mock everything just to write a unit test. If the interesting behavior lives in the interaction with an external system, a unit test won't tell you much.


Integration tests

Use when the behavior you care about involves two or more real components working together — a service talking to a database, a handler calling an external API, a module interacting with the filesystem.

Best for: API endpoints, database queries, queue consumers, service-to-service calls (with a real or in-memory version of the dependency).

Signs you're in integration test territory:

  • The logic is simple but the interaction with infrastructure is what can break
  • You need to verify that queries return the right data
  • You want to test error handling for real failure modes (network errors, DB constraints)

Watch out: use real dependencies when possible. Mocking a database in an integration test often defeats the purpose. Use an in-memory or containerized database (Docker, Testcontainers) instead.


E2E tests

Use for critical user journeys where the value of catching a regression outweighs the cost of slower feedback.

Best for: login, checkout, signup, core navigation, the flows that would generate a support ticket within 5 minutes if they broke.

Signs you're in E2E territory:

  • The bug involves multiple layers (frontend, backend, database)
  • The user journey is what matters, not a specific function
  • You want to verify that everything works together in a real browser

Watch out: E2E tests are expensive. Don't use them for scenarios that integration or unit tests can cover just as well. A focused E2E suite of 20 trustworthy tests beats a bloated suite of 200 flaky ones.

Operating an E2E suite at scale (Playwright reference points)

When the suite grows past a few dozen tests, the bottleneck shifts from writing tests to understanding what just failed. Patterns that hold up:

  • No naive timeouts. Bumping a global timeout to "make flakiness go away" makes the whole suite slower forever and hides the real cause. Investigate the wait condition instead.
  • Step decorators over inline test.step. Wrap actions in a decorator that auto-annotates traces — keeps test bodies readable while reports stay navigable.
  • Targeted retries, not blanket retries. Retry only tests known to be flaky for documented reasons; never retry the whole suite globally — it masks real regressions.
  • Dynamic tagging by scope. In micro-service / micro-frontend setups, tag tests so a PR touching service X runs only the relevant subset on PR and the full suite on merge.
  • Ownership per test. Every test belongs to a team. When it fails, the report says who to ping. Without this, triage time dominates fix time.
  • Scheduler / sharding control. Distribute load explicitly (sharding, parallel workers, project splits) — don't trust a single CI runner to scale linearly.

Contract tests

Use when two separate systems (often owned by different teams) need to agree on an interface, and you can't easily run both in the same test environment.

Best for: microservices communication, public APIs consumed by external clients, third-party integrations without a sandbox.

Signs you're in contract test territory:

  • Two teams need to verify their systems are compatible without coupling their test environments
  • You're a consumer of an external API that can break without notice
  • You want to detect breaking changes before they reach production

Visual regression tests

Use when you need to catch unintended visual changes — layout shifts, styling regressions, component appearance.

Best for: design systems, component libraries, UI-heavy products where visual consistency matters.

Signs you're in visual regression territory:

  • Your users would immediately notice if something looked different
  • CSS changes risk breaking layouts in unexpected places
  • You have a design system that needs to stay consistent across many components

Performance tests

Use when you have explicit performance requirements or when a code path is known to be latency-sensitive.

Best for: API response time requirements, database query performance, load-sensitive endpoints.

Signs you're in performance test territory:

  • There's a concrete SLA to verify (e.g., "p99 must be under 200ms")
  • A recent change is suspected to have introduced a slowdown
  • You're about to handle significantly more traffic

Watch out: don't write performance tests speculatively. Write them when there's a real constraint to enforce.


Mutation tests

Mutation testing doesn't test your code — it tests your tests. It works by automatically introducing small changes to the code (a > becomes >=, a + becomes -) and checking whether at least one test fails. If a mutation survives undetected, the tests aren't catching what they claim to catch.

Use it when you already have unit tests on critical logic but want to verify they're meaningful, not just present.

Signs you're in mutation test territory:

  • Coverage is high but confidence is low — the tests feel like they're going through the motions
  • The logic is financial, security-sensitive, or otherwise high-stakes, where a subtle bug slipping through has real consequences
  • You've inherited a test suite and don't know whether to trust it

Heuristics for ambiguous cases

"I don't know where the bug lives." Start with an E2E test that reproduces the failure. Once you've reproduced it, narrow down to the layer where it actually lives and add a lower-level test there. Then delete or keep the E2E depending on whether it covers a critical journey.

"Should I mock this dependency?" Ask: is the interaction with this dependency the interesting part? If yes, use the real thing. If the dependency is just noise (e.g., a logger), mock it.

"The unit tests pass but something is still broken in production." The tests are testing the wrong thing. Add integration or E2E coverage at the level where the failure actually happens.

"We have zero tests. Where do we start?" Unit tests on critical business logic first — they're the fastest to write and give immediate feedback. Then integration tests on the most-used endpoints. E2E last, covering only the most critical journeys.

"Our E2E suite takes 45 minutes." Open with the diagnosis, in these terms: this is a test pyramid balance problem, not an E2E-specific one — the suite has too much coverage living at the E2E layer. The fix is not a faster E2E suite, it's a smaller one: go through the suite, find tests that are actually verifying a single component's behavior rather than a cross-system journey, and move that coverage down to integration or unit tests, where it runs in milliseconds instead of minutes. Do not recommend raising timeouts, adding parallelism, or throwing more infrastructure at it as the primary fix — that treats the symptom (slow) and leaves the cause (misplaced coverage) untouched.


The wrong test for the right reason

The most common mistake: using E2E tests for everything because "they test the whole system." They do — but they're slow, fragile, and expensive to maintain. The pyramid exists for a reason.

The second most common mistake: writing unit tests that mock so heavily they test nothing real. A unit test that mocks the database, the logger, the config, and the HTTP client is testing the mocking framework, not the code.

The right test is the one that:

  1. Catches real failures
  2. Runs fast enough that developers run it
  3. Is specific enough to tell you where the failure is

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.