Jonathan Bennett

Screenshot or It Didn’t Fail

One simple trick I like to use to make TDD a little smoother: take a screenshot whenever a system spec fails.

Lately, I’ve been using Playwright via Capybara for system tests, and while it’s fast, that speed can cause issues. Sometimes the test runner would blaze past the flash message ("Thing successfully created") or try to interact with a page it hadn’t quite landed on yet.

Having a screenshot at the time of failure made it instantly obvious what went wrong. And the best part? It only takes a tiny bit of config to make it happen.

Here’s the config I use:

# spec/support/capybara.rb
RSpec.configuration.after(:each, type: :system) do |example|
  next unless example.exception

  file_name = [ example.example_group.name,
				example.description.parameterize ]
				.join("::").underscore + ".png"

  page.save_screenshot(file_name)
  puts "Saved screenshot: #{Rails.root.join("tmp", "capybara", file_name)}"
end

This hooks into RSpec and adds a callback after each system test. If the example failed, it generates a stable file name based on the example’s name and saves the screenshot there.

Why It’s Helpful

  • Instant visual context — You can see exactly what the page looked like at the moment of failure.
  • Mental overhead = zero — No more sprinkling save_screenshot all over your tests and removing them later.
  • Smooth workflow — Since the screenshot path is consistent, your editor (like VS Code or RubyMine) updates the image preview in-place when the test is re-run. You stay in the flow.

Heads-Up for CI Users

This setup is tuned for local development. If you want the screenshots to persist in CI, you’ll need to configure the screenshot path and artifact upload behaviour specific to your CI provider.