You know the feeling. You run bundle exec rspec and instead of a clean wall of dots, you get this:
❯ bundle exec rspec
DEPRECATION WARNING: Defining enums with keyword arguments is deprecated and will be removed in Rails 8.0. Positional arguments should be used instead
.......Warning: The code in the `before_worker_boot` block will not execute in
the current Puma configuration...
............Checking for expected text of nil is confusing and/or pointless...
...Checking for expected text of nil is confusing and/or pointless...
..WARNING: Using the `raise_error` matcher without providing a specific error...
.....Payment ID: 2789
Payment2 ID: 2790
.........true
true
Your eyes water. Your OCD bleeds. Somewhere, a Toyota engineer reaches for the Andon cord.
Drop everything. Yes, everything. That critical production bug? It can wait. The six-month
feature you are one PR away from shipping? Not important. There is only one priority now,
and it stares back at you from your terminal in a cascade of deprecation warnings and
orphaned puts calls from 2019.
The. Output. Must. Be. Cleaned.
…right after this other thing
Except, of course, you don’t drop everything. You scroll past it. You’ve always scrolled past it (I always scroll past it). There’s a real bug to fix, a PR to review, a meeting in ten minutes. The noisy output is annoying, but it’s not a crisis. It goes on “the list”.
And there it stays.
The smoke alarm problem
That pesky noise compounds though.
Every time you run the suite and scroll past a wall of warnings, you’re training yourself
to treat the output as wallpaper. Which is fine, until it’s not. A real deprecation that’s
about to become a breaking change. A stray puts that’s leaking sensitive data in CI logs.
A warning that signals a subtle misconfiguration in your test environment.
It’s the smoke alarm that goes off every time someone makes toast. Eventually you stop evacuating. You know how that story ends.
The noisy suite isn’t a crisis. But it is slowly eroding your ability to notice when something actually is.
The bottom of the list
Cleaning up test output is genuinely tedious work. For each piece of noise you need to:
- Find the test that’s producing it
- Reproduce it in isolation
- Track down the root cause (which is rarely where you expect)
- Fix it without accidentally breaking what the test covers
- Verify the output is actually gone
- Commit, ship and verify nothing broke
Then do it again. For every warning. Every orphaned debug call. Every gem that decided its deprecation notice belongs in your test output.
It’s not hard, necessarily. It’s just slow, fiddly, and aggressively unglamorous. The kind of thing that’s very easy to justify deferring when there’s a feature to ship.
I know skill-fu
This is exactly the kind of work AI is good at.
So I built a Claude skill, creatively named clean-rspec-output, that works through noisy RSpec output one issue at a time. It
- Captures the full suite output
- Scans for the unexpected
- For each it:
- Locates the source test
- Reproduces the output in isolation
- Fixes the root cause
- Verifies the fix
- Commits
One fix per commit, so you can review or cherry-pick each change independently.
The whole thing runs while you get on with something else. Afterwards, bliss:
❯ bundle exec rspec
..............................................................................................................................
..............................................................................................................................
..............................................................................................................................
Finished in 4 minutes 2 seconds (files took 8.06 seconds to load)
892 examples, 0 failures
Don’t do the bad thing
The tempting shortcut (especially for machines) when test output is noisy is to simplify the test until the noise stops. Delete the code branch that’s producing the warning. Use a different value in the assertion, one that happens not to trigger the deprecation.
The output disappears. The test still passes. Nobody notices that you’ve just quietly removed a scenario the test was written to cover. Bad bot.
The skill won’t do this. Or at least, there are some strong attempts at guardrails to defend against this kind of lazy just-get-my-test-to-pass AI fun. A fix may change how a test runs. It must not change what it covers. If a warning is coming from a code path the test genuinely needs to exercise, the fix belongs in the application code or test configuration, not in the test itself.
These guardrails were driven by dogfooding the skill repeatedly against a number of 100K+ LOC test suites until this author was satisfied with the results.
Getting started
Install the skill by copying it to your Claude Code skills folder:
git clone https://github.com/thoughtbot/clean-rspec-output ~/.claude/skills/clean-rspec-output
Then from inside a Claude Code session, in the root of your Rails project:
/clean-rspec-output
It’ll ask which branch to work on before doing anything. From there, it handles the rest.
Try it out in some gnarly codebases and see how it goes. Hopefully it saves you some time and resatisfies your OCD. But if you notice any funky behaviour or unpleasantness, feedback is always welcome!