Test First logo

Test First

Community
llopresto87
test-first

The test-shaping technique applied inside the test-first protocol — pick the lowest test level that exercises the behavior (unit, integration, contract, e2e, golden, property-based, evaluation), name the test after the spec contract, and assert one outcome per test. The workflow itself (entry conditions, RED-GREEN-REFACTOR-COMMIT gates, variants, exceptions) is the test-first protocol.

Overview

Publisherllopresto87
RepositoryCypress
Skill nametest-first
Stars
113
Forks
6
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by llopresto87 on GitHub. Read the source before you install it.

Installation

Install the Test First AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/llopresto87/Cypress/tree/main/skills/test-first
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/llopresto87/Cypress.git /tmp/Cypress
mkdir -p .claude/skills
cp -r /tmp/Cypress/skills/test-first .claude/skills/test-first
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Test First in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Test First on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Test First is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

test-first (the test-shaping technique)

The cycle (RED → GREEN → REFACTOR → COMMIT, its per-phase gates, the characterize-first rule, the bug-fix and refactor variants, the migration safety gate, and the recorded exceptions) lives in docs/graph/protocols/test-first.md, the one home for the workflow. This skill owns the craft of shaping each test the cycle asks for.

Test level selection

Pick the lowest level that exercises the behavior.

LevelUse when
UnitPure logic, transformations, parsers, validators.
IntegrationCrossing an adapter (DB, file, network, SDK, model).
ContractAPI endpoints, structured outputs, message schemas.
End-to-endCritical flows, one or two per flow.
Golden / snapshotDeterministic transforms, prompts, renderers.
Property-basedAlgorithms where the property is clearer than examples.
EvaluationLLM/VLM behavior, with rubrics and pass thresholds.

Test shape

  • The name names the contract. The spec §4 contract slug, transformed for the language's convention (test_submit_valid_form_returns_2xx, submitValidFormReturns2xx, …). The reviewer should be able to read the test names and reconstruct the spec. A name that claims more than its body asserts is worse than an empty assertion: the standard way to ask "is this covered?" is to search test names, and a false name answers yes.
  • The body is Given/When/Then. Set up Given, perform When, assert Then.
  • One outcome per test, or per named sub-case (or one assertion group about the same outcome), so a failure names its cause. When several outcomes follow from one expensive action, the action runs once and each outcome is asserted as its own named sub-case, so no first failure hides the rest.
  • Reusable code is tested over its consumers, not for one of them. When the code under test serves many consumers (plugins, packs, tenants, configurations, projects), the default test checks a property over every consumer on disk, or checks the behavior over one generic, synthetic fixture consumer (never production data, kernel §4). Name tests generically and assert generic values: a test that pins a real consumer's literals ties the shared code to one customer and breaks when that customer changes. The same holds for a property of a factory, a table, or a loop: one case over the whole collection.
  • A test joins the class that owns its contract. A RED born from a review finding extends the test class (file, fixture group, suite) that already asserts the contract the finding is about, so the contract's tests stay in one place and share their setup. Starting a new class is a choice with a stated reason, such as a setup the owning class cannot give, written in the handback and in the spec's §10 beside the setup-sharing lines; without one, the contract's coverage splits across classes that drift apart.

Answer a coverage lint with a real test (test-first.no-lint-only-tests)

A coverage lint can report a contract that no test names. Answer it in one of two ways: cite the contract's slug in the existing test that already asserts the contract, or, when none does, write the test the contract needs, because the gap is real. A test that asserts nothing new only turns the lint green.

Proportionate checks (test-first.proportionate-checks)

The one home for when a check exists and what it may cost. A check is a test, a gate, or a check inside delivered code (validation, a guard, a fail-closed path). Other nodes link here; they do not restate it.

  • A check exists only for a named, real blast radius. Name what breaks, and for whom, if the check is absent. No name, no check. Spec size does not set test count: one test may cover several failure modes, and a failure mode with no real blast radius gets none.
  • A spec's tests are designed as one set, before any test code. First survey what exists: the tests already in the suite, the contracts they already cover, and the setup they share. Then plan the tests across the whole spec, not increment by increment, and merge the overlaps the plan shows: two increments whose contracts one test can assert get that one test. The §10 mapping is therefore not one-to-one with increments: a row may cite a test another increment wrote, by its path and name. Planned whole, the set is written whole: the owner decided on 2026-10-14 that a spec's failing tests are written in one RED wave and its mutation pass runs once, batched at the end. The plan gives a spec's RED increments no Depends on: among one another, so grill-lint.py --waves puts them in one wave (delegation.waves) and the tester writes them together, not one increment at a time; a RED that cannot fail for the right reason until another increment's behaviour exists is the exception, named with its reason in the plan. Mutation follows delegation.mutation-at-end.
  • A change with nothing to get wrong earns no new test. Before RED, name what the test could catch that the edit being present does not already guarantee. A declarative edit (a selector, a pipeline stage, a route, a flag, a config key, a mapping entry, a label) usually has nothing: its only test reads back the value just written, goes red because the line is absent and green because it is present, and so proves only the diff. Prove such a change by the run that shows its effect: an existing test or gate that already exercises the surface, or the cheapest real run (a dry-run where it exercises the surface, a validate command, one pipeline run; against live infrastructure a dry run is structural evidence only, method.host-parity), named with its result in the handback. The declaration earns a test when it holds logic that can be wrong while present: a pattern (regex, glob, wildcard), a condition, an order or precedence that changes the output, or a computed value. That test feeds it inputs and asserts what it selects.
  • A test is cheaper than its subject. It asserts one behavior and never re-implements the code under test. A long setup, a helper of its own, or a comment naming the load-bearing line marks it over budget, and the answer is a smaller test or none; one that would need more code than its subject means the level or the design is wrong: hand it back unwritten, with that finding.
  • Assert one mechanism, by its behavior. A test that passes on either of two implementations asserts nothing: assert the one mechanism, and escalate a contract that permits two shapes as a spec ambiguity. Where a behavioral assertion is available, assert the behavior rather than that code calls a function, imports a module, or takes a path; a mock that only counts calls fails on a rename and passes on wrong behavior. Mocks for time, randomness, network, and external services stay fine.
  • Full rigor is for high blast radius only. Mutation proof and planted violations re-run after a refactor belong to the classes delegation.mutation-at-end makes mandatory, once per batch. Elsewhere a RED seen failing for the right reason is the proof, plus any sample that rule records.
  • The owner adds checks to runs; the seed adds none. A new check joins the project's automated runs, or the running product, only by a recorded owner decision. An escaped bug earns a regression test; a new gate is protocol.verify-new-gates's call.
  • Shrink on purpose. A suite only grows unless someone cuts it. Every deleted test names its survivor, the test that still fails when it would have; with no survivor the deletion is a recorded coverage loss. A regression test merges only into a named survivor (the regression rule in protocol.test-first). Consolidation is its own planned increment (protocol.grill). The tool corpus catalogs a lint for suite smells, tool-corpus/testing/test-hygiene-lint.md.

Reference files

  • docs/graph/protocols/test-first.md : the workflow this technique serves.
  • docs/graph/templates/spec.template.md : where contracts live (§4) and test mapping is recorded (§10).
  • docs/graph/agents/04-tester.md : the agent that owns the cycle.
  • docs/graph/agents/02-implementer.md : the agent that writes GREEN.

Frequently asked questions

What does the Test First AI skill do?

The test-shaping technique applied inside the test-first protocol — pick the lowest test level that exercises the behavior (unit, integration, contract, e2e, golden, property-based, evaluation), name the test after the spec contract, and assert one outcome per test. The workflow itself (entry conditions, RED-GREEN-REFACTOR-COMMIT gates, variants, exceptions) is the test-first protocol.

Why use Test First on TypingMind?

Because you install it once and use it with any model. Test First is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Test First in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/llopresto87/Cypress/tree/main/skills/test-first. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Test First?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Test First?

As many as you like. As long as a model supports skills, you can use Test First with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Test First AI skill free?

Yes. It is published on GitHub by llopresto87 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇