Source profileQuality 92/100

bostonaholic/team/skills/test-style/SKILL.md

test-style

Test style rules and the flaky-test red-flag catalog — behavior-not-implementation, DAMP setup, narrow assertions, deterministic-input rules (clock, randomness, ordering, hermetic boundaries), the fidelity ladder, and the audit checklist. Load when writing tests, auditing test quality, or reviewing changed test files for flaky patterns.

Source repository stars
11
Declared platforms
0
Static risk flags
0
Last source update
2026-08-28
Source checked
2026-08-28

Decision brief

What it does: where it fits

These rules govern every acceptance test written under skills/test-first-development/SKILL.md, and they are the bar reviewers hold changed test files to. Each rule catches a different class of test-suite decay.

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/bostonaholic/team --skill "skills/test-style"
    Safe inspection promptEditorial

    Inspect the Agent Skill "test-style" from https://github.com/bostonaholic/team/blob/bb84b1ff5bd32f4910d754d5ca1f4398e63bf98b/skills/test-style/SKILL.md at commit bb84b1ff5bd32f4910d754d5ca1f4398e63bf98b. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      Test behavior, not implementation

      Tests assert externally observable outcomes. A refactor that preserves behavior must leave every acceptance test green. Tests that break on internal restructuring are change-detectors — they produce noise on every refactor without proving the system works.

      Assert on what the caller observes: return values, persisted state, effectsDo not assert on which private methods were called in which order, unlessInteraction tests verify state-changing calls only. Never assert on
    2. 02

      Tests are DAMP, not DRY

      Test code is read far more than it is run. Inline the setup a reader needs to understand a failing test. Tolerate duplication. Favor a linear arrange-act-assert story.

      Pass the asserted value through helpers: createaccount(BALANCE), notNo if, no loops, no string-building inside a test body — they can carryExtract helpers only when the same setup appears across many tests AND the
    3. 03

      Narrow assertions

      Assert on the specific field the test cares about (account.balance == 2000), not full equality on a complex object. Reserve full-snapshot assertions for at most one default test per common case.

      Assert on the specific field the test cares about (account.balance == 2000), not full equality on a complex object. Reserve full-snapshot assertions for at most one default test per common case.Use subset matchers when available (comparingExpectedFieldsOnly, UnorderedElementsAre, protocmp.FilterField). Brittle failures are a signal that the test toolkit is missing a matcher — propose one rather than blaming th…
    4. 04

      Test failures must be actionable

      A failing test must be diagnosable from name + assertion output alone, without rerunning.

      EXPECTOK(loadMetadata()) beats EXPECTTRUE(loadMetadata().ok())assertEqual(actual, expected) beats assert(predicate) because it printsTest names describe behavior, not method: sendsEmailWhenBalanceIsLow, not
    5. 05

      Wait for the condition. Never sleep

      Replace every fixed sleep(N) with a wait-for-condition primitive (exist, not-exist, wait-to-exist with timeout + interval). A fixed sleep both masks race-condition bugs and pads runtime when the system is fast.

      Replace every fixed sleep(N) with a wait-for-condition primitive (exist, not-exist, wait-to-exist with timeout + interval). A fixed sleep both masks race-condition bugs and pads runtime when the system is fast.

    Permission review

    Static risk signals and limitations

    No configured static risk pattern was detected

    This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score92/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars11SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    bostonaholic/team
    Skill path
    skills/test-style/SKILL.md
    Commit
    bb84b1ff5bd32f4910d754d5ca1f4398e63bf98b
    License
    MIT
    Collected
    2026-08-28
    Default branch
    main
    View the original SKILL.md

    Test Style Rules

    These rules govern every acceptance test written under skills/test-first-development/SKILL.md, and they are the bar reviewers hold changed test files to. Each rule catches a different class of test-suite decay.

    Test behavior, not implementation

    Tests assert externally observable outcomes. A refactor that preserves behavior must leave every acceptance test green. Tests that break on internal restructuring are change-detectors — they produce noise on every refactor without proving the system works.

    • Assert on what the caller observes: return values, persisted state, effects visible to other components.
    • Do not assert on which private methods were called in which order, unless the call itself is the observable behavior. One example is a message published to an external channel.
    • Interaction tests verify state-changing calls only. Never assert on query-only calls.

    Tests are DAMP, not DRY

    Test code is read far more than it is run. Inline the setup a reader needs to understand a failing test. Tolerate duplication. Favor a linear arrange-act-assert story.

    • Pass the asserted value through helpers: create_account(BALANCE), not create_account() that hides the value the assertion checks.
    • No if, no loops, no string-building inside a test body — they can carry the same bug as the code under test.
    • Extract helpers only when the same setup appears across many tests AND the helper does not hide assertion-relevant inputs.

    Narrow assertions

    Assert on the specific field the test cares about (account.balance == 2000), not full equality on a complex object. Reserve full-snapshot assertions for at most one default test per common case.

    Use subset matchers when available (comparingExpectedFieldsOnly, UnorderedElementsAre, protocmp.FilterField). Brittle failures are a signal that the test toolkit is missing a matcher — propose one rather than blaming the test author.

    Test failures must be actionable

    A failing test must be diagnosable from name + assertion output alone, without rerunning.

    • EXPECT_OK(loadMetadata()) beats EXPECT_TRUE(loadMetadata().ok()) because the failure prints the actual error.
    • assertEqual(actual, expected) beats assert(predicate) because it prints both values.
    • Test names describe behavior, not method: sendsEmailWhenBalanceIsLow, not testProcessTransaction_1.

    Wait for the condition. Never sleep

    Replace every fixed sleep(N) with a wait-for-condition primitive (exist, not-exist, wait-to-exist with timeout + interval). A fixed sleep both masks race-condition bugs and pads runtime when the system is fast.

    Assert outcomes, not interleavings

    A test whose result depends on thread or promise scheduling passes only when the scheduler cooperates. Accept every valid interleaving, or make the interleaving deterministic.

    • join()/await every concurrent task before asserting — never assert mid-flight.
    • Assert order-independent properties on concurrently produced results — set membership or a sorted comparison, not results[0] === "A".
    • Where ordering genuinely matters, impose it with latches/barriers (CountDownLatch, chained promises) instead of relying on scheduler luck.

    Control the clock

    Never read the real wall clock in a test — inject or freeze it (vi.setSystemTime, fake timers, Clock.fixed, freezegun). Each sub-pattern below ships a time-bomb: a test that is green today and permanently red on some future date.

    • No assertion against "now": new Date(), Date.now(), datetime.now() feeding an assertion.
    • No hard-coded future expiry: expiresAt: "2030-01-01", cert notAfter — generate expiring artifacts at setup, relative to the frozen clock.
    • No naive calendar arithmetic on "now": addMonths / +1 day assumes month lengths, 24-hour days, and no DST. It fails on month-end, leap day, and DST-transition days.
    • No TZ-naive date construction: new Date("2023-08-31") parses as UTC midnight and shifts a day in negative-offset zones.

    Past or fixed date literals with an explicit timezone are the sanctioned form.

    Bad:

    // Bad — wall-clock read feeds the assertion; hard-coded future expiry.
    // Green today, permanently red once the clock crosses the literal.
    const token = { expiresAt: "2030-01-01" };
    expect(isValid(token, new Date())).toBe(true);
    

    Good:

    // Good — frozen/injected clock; expiry derived from it.
    const now = new Date("2024-06-15T12:00:00Z");
    const token = issueToken({ now, ttlDays: 30 });
    expect(isValid(token, now)).toBe(true);
    

    Seed all randomness

    An unseeded RNG feeding an assertion is a defect, not a convenience — generated data can collide with the asserted value.

    • Seed every generator the test touches: faker.seed(12345), a seeded Random(seed) — never bare Math.random() or uuid.v4() in asserted data.
    • Better: explicit fixed inputs. createUser({ name: "Bob" }) cannot collide. createUser({ name: faker.person.firstName() }) can.

    Tests own their state — any order, any host

    A test builds its own preconditions and tears down what it creates. A test that passes only in a specific order, or only after another test has run, is order-dependent — a leading flakiness cause.

    • No static or module-level mutable state shared across tests. Reset singletons and caches in beforeEach/afterEach.
    • Every DB row, file, cache entry, or env var a test creates gets a teardown (prefer transaction rollback).
    • Never assert on state a different test produced. The suite must pass in any order and on any host.

    Impose order before asserting it

    Hash map/set iteration, os.listdir, and queries without ORDER BY have no defined order — a positional assertion on them is platform-dependent luck.

    • Add an explicit ORDER BY / .order_by() / sort before any positional assertion (results[0]).
    • Or assert order-independently: set membership, unordered-elements matchers.
    • Never compare an ordered structure against a set-backed result.

    Hermetic boundaries

    The test must not depend on anything outside the process it controls.

    • No real network or external services — stub the boundary (nock, WireMock, msw) and inject the client.
    • No hard-coded ports for embedded servers/DBs — dynamic allocation (port 0, TestContainers) plus guaranteed teardown. Fixed ports collide under parallel CI.
    • Guarantee teardown of every opened connection, file, or socket. Use try/finally, using, defer, or the framework's fixture teardown. A leaked handle can fail a later test.
    • No locale/platform-format assertions without pinning — pass the locale explicitly, use path.join() / os.EOL, set TZ/LANG in the harness.
    • No exact float equality — toBeCloseTo(0.3), not toBe(0.1 + 0.2). compare with a tolerance.

    Fidelity ladder: real > fake > mock

    When a test needs a collaborator, prefer in this order:

    1. Real — the production implementation. Highest fidelity.
    2. Fake — a lightweight in-memory equivalent maintained by the real implementation's owner. Use when the real is too slow or network-bound.
    3. Mock — last resort, primarily for error-path injection or when neither real nor fake exists.

    Default-to-mocking collapses fidelity and produces mock chains that mirror production graphs without surfacing real bugs.

    Do not mock types you do not own

    If a vendor type needs to be substituted, wrap it behind your own interface and mock the wrapper. Upstream API changes then ripple through one boundary instead of through every test.

    E2E reserved for critical user journeys

    End-to-end tests are expensive — budget about one engineer-week per quarter per E2E test to keep stable. Reserve them for a small list of user goal-plus-task workflows. Do not chase exhaustive E2E coverage.

    Test workflows, not just features

    Features ship into a system. Bugs live at the seams. When the design introduces a feature whose behavior overlaps an existing one, the acceptance-test list must include at least one cross-feature interaction test.

    Audit checklist

    Before confirming failures, audit each test against this bar. Every "NO" is an issue to fix. The rules above spell each check out in full. The bar below is the audit checklist.

    CheckPass criterion
    Behavior-namedTest name describes the behavior, not the method. sendsEmailWhenBalanceIsLow, not testProcess_1.
    Narrow assertionThe assertion targets the specific field/effect under test. No full-equality on complex objects unless that IS the contract.
    Actionable failureIf the test fails, the failure message names the failing condition. EXPECT_OK(...) not EXPECT_TRUE(...ok()).
    No sleepsNo sleep() for synchronization. Use wait-for-condition primitives.
    Deterministic inputsNo wall-clock reads, unseeded randomness, order-dependent or shared-state assumptions, race-interleaving assumptions, positional asserts on unordered collections, real network, hard-coded ports, or exact float equality feeding an assertion. Clock frozen/injected. RNG seeded.
    No test logicNo if, no loops, no string-building inside the test body.
    One scenario per testThe test verifies one behavior and runs independently in any order.
    DAMP setupSetup the reader needs to understand the test lives in the test (or a helper that takes the asserted value as a parameter).
    Fidelity ladderReal > fake > mock. No mocks where a fake is feasible. No mocks for types you do not own — wrap them.

    When reporting issues, cite the failing check by name (e.g., "Test 7 fails the Narrow assertion bar — it asserts on the full order object when only order.total is the slice's contract").

    Flaky-test red flags (reviewer checklist)

    The reviewer-facing catalog of nondeterministic inputs. Any test whose outcome depends on one of these flags on first occurrence — the severity regime lives in skills/code-review/SKILL.md ("Flaky-test red flags"). A time-bomb example pair lives under "Control the clock" above.

    • Time/date dependence, incl. time-bombsnew Date(), Date.now(), datetime.now() feeding an assertion. A future date literal in a fixture (expiresAt: "2030-01-01", cert notAfter). Naive calendar arithmetic on "now" (addMonths, month-end/DST/leap assumptions). TZ-naive date construction. Past/fixed date literals with an explicit TZ do not flag.
    • Fixed-sleep / timed waitssleep() for synchronization: Thread.sleep(ms), setTimeout-as-wait, cy.wait(3000), page.waitForTimeout(...). A bounded wait whose success is asserted (assertTrue(latch.await(100, MS)) — a capped wait still flags). Tests legitimately about time require a frozen/fake clock — a real sleep to observe a delay still flags.
    • Concurrency / race interleaving — assertions assuming a completion order across threads, Promise.all, or executors. Shared state mutated without synchronization. Missing join()/await before asserting. Order-independent assertions (Set comparison, sorted) do not flag.
    • Test-order dependence & shared mutable state — static/module-level mutable state written by a test. State (DB row, file, env var) created with no teardown. A test reading state another test produced.
    • Unseeded randomnessMath.random(), uuid.v4(), faker.* without faker.seed(n) feeding an assertion. Seeded randomness does not flag.
    • Real network / external services — live URLs or SDK clients in a test with no stub/interceptor at the boundary.
    • Resource leaks & hard-coded ports — a fixed port for an embedded server/DB (collides under parallel CI). An opened connection, file, or socket with no guaranteed teardown.
    • Unordered-collection order assumptions — positional assertions on hash map/set iteration or on a query with no ORDER BY.
    • Exact float equalityexpect(0.1 + 0.2).toBe(0.3). Require a tolerance/epsilon comparison.
    • Platform/environment dependence — hard-coded path separators or line endings. Locale/TZ formatting asserted against a fixed string. CPU-count or CI-parallelism assumptions.

    Frequently asked questions

    What to verify before installation and use

    What does the test-style source document cover?

    These rules govern every acceptance test written under skills/test-first-development/SKILL.md, and they are the bar reviewers hold changed test files to. Each rule catches a different class of test-suite decay.

    How do I install test-style?

    The source record exposes this install command: npx skills add https://github.com/bostonaholic/team --skill "skills/test-style". Inspect the command and pinned source before running it.

    Alternatives

    Compare before choosing

    Computed 10045,960

    coreyhaines31/marketingskills

    ab-testing

    When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program

    Computed 10029,236

    garrytan/gbrain

    bulk-ingestion

    End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.

    Computed 10025,136

    alirezarezvani/claude-skills

    app-store-optimization

    App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist

    Computed 1005,277

    dotnet/skills

    migrate-vstest-to-mtp

    Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing