runtimeanalyz.ing

← All capabilities

specs_that_reach

CLI · LSP · MCP Pro

Run only the specs that reach your change. The spec examples whose recorded runs reach a method. After a change you rerun those examples alone, and the red-green loop takes seconds.

enrollment_spec.rb:8
unlock_next
Enrollment you changed this
def unlock_next
  curriculum
    .unlocked_for(student)
    .reject(&:completed?)
end
enrollment_spec.rb:21
unlock_next
progress_spec.rb:44
unlock_next
via ProgressController#update
student_dashboard_spec.rb:12
unlock_next
via 3 calls
curriculum_spec.rb:14 doesn't reach it
never calls it
Run rspec $(ra specs_that_reach --since HEAD) → 4 examples, 0 failures · 0.8s
Each recorded call tree is stamped with the spec example that produced it, so a changed method maps back to the examples that reached it at any depth.

The problem

Red-green-refactor depends on a fast loop. Once the suite takes minutes, the usual substitute is to run one spec file by hand and hope it is the right one. That misses the example three directories away that also goes through the method you changed, and you find out in CI.

A recording of the examples running says which of them reach a method, which file names and requires do not.

The fix

Suppose you change Enrollment#unlock_next. In your editor, a code lens above the method shows what reaches it:

# ▶ reached by 4 examples · 12 app runs
def unlock_next
  curriculum.unlocked_for(student)
end

On the command line:

$ ra specs_that_reach Enrollment#unlock_next
Enrollment#unlock_next
· reached by 4 examples
spec/models/enrollment_spec.rb:16
spec/models/enrollment_spec.rb:23
spec/models/enrollment_spec.rb:5
spec/requests/progress_spec.rb:4

It prints file:line locations, so its output can be passed to rspec:

$ rspec $(ra specs_that_reach Enrollment#unlock_next | grep '^spec/')
3 examples, 0 failures
Finished in 0.07 seconds

--since REF takes the methods changed in a git diff and lists the union of the examples that reach any of them. Your agent, your editor and a pre-push hook can use it to get the examples a change touches.

How it works

Every call tree in the recording is stamped with the spec example that produced it. That gives a map from each example to every method it reached, and specs_that_reach reads it backwards: from a method to every example that reached it, directly or through any depth of calls.

It lists individual examples, because a file with forty examples might have two that reach your method.

Run it on your app

The output on this page comes from our example Rails app, and it is regenerated whenever a tool changes. These are the commands behind it. On your own app, run ra record first, then put your own class, method or file in their place.

ra specs_that_reach 'Enrollment#unlock_next'
rspec $(ra specs_that_reach 'Enrollment#unlock_next' | grep '^spec/')

The method is app/models/enrollment.rb:10.

Reading the result

  • The map is as fresh as the last recording. A spec written since the last recorded run is missing from it until you run that spec once.
  • A request spec counts as an app run. When a request spec drives a controller, the controller stamps its own trees with the request, so the lens counts those examples as app runs. The example app’s spec/requests/progress_spec.rb is one of the 12.
  • A new method has no examples in the map. On the first red run that is expected, because the spec you are writing is the one that will reach it.
  • The map is keyed by method. A change to configuration, a YAML file or a migration can change behaviour without touching a method, so run the full suite for those changes.

Every tool reads the same recording. What gets recorded and how far to trust an answer are on the questions page.

testing_pyramid

CLI · MCP Pro

Boundaries crossed through doubles alone. The calls between classes that your specs make through a double alone, with how many specs stub each one and how often your recorded app traffic made it for real, plus the number of examples in each spec directory.

See more →

dead_api

LSP · CLI Pro

Find dead public API. The public methods that no caller reached in any recorded run, including those whose only caller is their own spec. Shown as a hint in your editor.

See more →

split_interface

CLI · LSP · MCP Pro

The role interfaces in a class. Groups a class's public methods by which callers used them in the recording, and lists each group as a role interface to extract.

See more →