tdd/SKILL.md
Implement a change using test-driven development with RSpec. Guides the specify-encode-fulfill workflow.
npx skillsauth add jasonswett/llm-skills tddInstall 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.
$ARGUMENTS
I use something called "specify-encode-fulfill":
At a finer grain:
This follows Kent Beck's Canon TDD.
Before writing tests, follow this loop:
Specifications should take the form: "under scenario A, X happens; under scenario B, Y happens".
For guidance on designing good specifications, see test-design-review/SKILL.md.
Each scenario should map to an RSpec example group. If the specification is, for example "when a test suite run's status is 'passed', its label says 'Passed'", then the test should look like this:
describe "#label" do
context "when status is 'passed'" do
it "returns 'Passed'" do
test_suite_run = TestSuiteRun.new(status: "passed")
expect(test_suite_run.label).to eq("Passed")
end
end
end
Here's an example of a BAD way to write such a test:
describe "#label" do
it "returns the correct value" do
test_suite_run = TestSuiteRun.new(status: "passed")
expect(test_suite_run.label).to eq("Passed")
end
end
Of course it returns the "correct" value. What else could we ever want from our code? Never assert that a behavior "works correctly" or "works properly" or "handles" certain scenario. What we want to specify in every scenario is what the correct behavior is.
Before you write a test, picture the test you're going to write and where you're going to put it. Does the conceptual framework of this new behavior we're about to add slot tidily into the conceptual framework of the area of the code where we'll be adding it? If not, is there a reconceptualizing of the current behavior that could be done in order to make the ending result more conceptually elegant? If such a reconceptualizing is called for, suggest it to the user. If the user approves, abandon the current change, get to a clean working state, and, on a new branch, perform a refactoring. "Clean the kitchen before you make dinner." Then pause and consult the user and we'll begin again.
When writing the application code to fulfill a certain specification, write ONLY ENOUGH CODE to make the current test failure go away. Never use "defensive coding". Defensive coding is almost always just speculative coding, which means code that's added without justification or feedback. Once you've written the test, invoke a separate subagent with the /test-design-review command to scrutinize your test code. Then invoke another subagent with the /software-design-review command to scrutinize your application code.
This kind of thinking is bad:
That failure is pre-existing (unrelated to our change — it's in send_results). Our 6 new + existing specs pass. Want me to commit and push?
We don't make dinner in a dirty kitchen. If we discover a pre-existing failure, the right move is to pause, stash our changes, fix the pre-existing failure, then resume.
This is stupid and bad:
Bundler version mismatch. The task agent uses bundler 2.5.22 but the system has a different version. The tests can't run here. But the changes are straightforward — removed re-tagging and made preload_app_image return the image name.
Don't abandon tests immediately upon encountering the slightest difficulty.
testing
--- name: software-design-review --- # Design When invoked, unless otherwise directed, follow the following steps. Steps 1-6 should be autonomous; step 7 is interactive. You should also support "full self-driving" mode where you just apply all fixes to all violations without prompting. The user can pass "fsd" to invoke full self-driving mode. Note: all the following steps should be followed, strictly and literally, even for trivial-seeming changes. This skill applies just as much to test cod
testing
Review tests for design quality using test design guidelines.
development
# Model Name Migration Guide This guide describes how to rename a Rails model. We'll use renaming `Circle` to `Shape` as an example. ## Step 1: Rename the database table Create a migration to rename the table: ```ruby rename_table :circles, :shapes ``` Commit and deploy this change before proceeding. The old model code will continue to work because Rails looks up the table name from the model class, and the model still references the old table name until we update it. ## Step 2: Create new
tools
Improve performance