DEV Community

Fernando Shayani
Fernando Shayani

Posted on

Run RSpec tests on changed files only

I always do my best to run tests on my local machine before publishing a PR. However, depending on the size of the test base, this could be unsustainable.

To solve this, I at least run the tests on all *_spec.rb files of my current working branch (or stack of branches) that were changed (or created) since another branch. Usually, it’s main or staging.

Let’s look at the code below:

o feature-2/more-features
|   changed file: user_spec.rb
o bugfix/fix-users-controller-params
|   created file: users_controller_spec.rb
o feature-1/branch-1-new-feature
|   updated file: product_spec.rb
|   updated file: new_payment_service_spec.rb
o main
Enter fullscreen mode Exit fullscreen mode

This is a purely didactic example

This stack of branches has changed/created 4 spec files. Now, I want to run RSpec on only those four files, not on the entire test base.

To achieve this goal, I created a bash script to use git to list all changed *_spec.rb files and run the rspec command against them. Here is the code:

#!/bin/bash

# Set default branch name
branch_name="${1:-staging}"

# Get changed files with grep for _spec.rb extension
changed_specs=$(git diff --name-only --diff-filter=d "$branch_name" | grep _spec.rb)

# Check if any changed specs found
if [[ -z "$changed_specs" ]]; then
  echo "No changed _spec.rb files found between HEAD and $branch_name."
  exit 0
fi

echo "List of changed spec files:"
echo "$changed_specs"

# Run rspec with all changed specs
bundle exec rspec $changed_specs

echo "RSpec tests completed for changed _spec.rb files."
Enter fullscreen mode Exit fullscreen mode

Click here to view and download this gist

Save this file and give it a name (I use rspec_changed_files.sh).

Now, simply run it on your repo directory.

./rspec_changed_files.sh
Enter fullscreen mode Exit fullscreen mode

By default, it will find the changed files related to the staging branch, but you can adapt the code or override the branch on the command line with another branch name or commit hash:

./rspec_changed_files.sh main
Enter fullscreen mode Exit fullscreen mode

Output:

List of changed spec files:
spec/models/user_spec.rb
spec/controllers/users_controller_spec.rb
spec/models/product_spec.rb
spec/services/new_payment_service_spec.rb
....................

Finished in 0.60517 seconds (files took 1.81 seconds to load)
10 examples, 0 failures

RSpec tests completed for changed _spec.rb files.
Enter fullscreen mode Exit fullscreen mode

Happy testing!

Top comments (2)

Collapse
 
starswan profile image
Stephen Dicks

This is not quite what you want to do. What you need is to run all the tests that deal with the code that you have changed, not just the tests that have changed. There are existing tools for this - pronto can tell you which files have changed, guard will run tests as you change them, and there is an amazing gem github.com/toptal/crystalball which does exactly the behaviour I suggested above. But really you should run all the tests - if they are impractical to run locally, then maybe your project should invest some time in fixing that.?

Collapse
 
shayani profile image
Fernando Shayani

Hi Stephen. Thanks for the tip for Crystalball. I'll give it a try.