Rspec-core: Feature request: Run specs in line range

Created on 22 Dec 2016  ·  6Comments  ·  Source: rspec/rspec-core

While the existing functionality for running specific tests meets my needs most of the time for running individual tests or tests in a block, occasionally I want to run two or three adjacent tests that don't make up a block in themselves.

I'm aware that multiple "locations" can be specified when running the CLI, so this functionality can already be achieved by passing every line in the range via multiple :s, e.g. rspec spec.rb:10:11:12:13:14:15. But it would be nice to have smoother UI for this use case, perhaps something like rspec spec.rb --start-line 10 --end-line 15.

Would the maintainers consider a PR that added this feature?

Most helpful comment

Here's a fixed version:

RSpec.configure do |c|
  if ENV['LINE_RANGE']
    range_start, range_stop = ENV['LINE_RANGE'].split('-')
    range = Integer(range_start)..Integer(range_stop)
    c.filter_run_including line_number: lambda { |line_number| range.include?(line_number) }
  end
end

I hadn't actually tried the snippet before (I just typed it in the github comment box), so I made a few dumb mistakes (like forgetting to convert the start/stop to integers). I've confirmed this snippet works, though.

All 6 comments

The problem with --start-line 10 --end-line 15 is that lines are only meaningful in relation to specific files. We used to support --line-number (in addition to the :num suffix) but did away with it because it added a lot of complexity given you can pass multiple files names...whereas file_name.rb:10 is unambiguous and clear that the line number applies only to that specific file.

If we were to support this, I would ideally want it to be only in the CLI option parser, so that whatever form in which we support this winds up being translated to a form like 10:11:12:13:14:15; adding more complexity to how we do line number filtering would add a great deal to our maintenance burden, I think. But even that isn't necessarily simple; we already support "fuzzy" line number matching where we match each given line number against the nearest example or group on or above the line number, which might not do what you want.

I haven't tried this, but I think you could support this via ENV vars and some simple config:

RSpec.configure do |c|
  if ENV['LINE_RANGE']
    range_start, range_stop = ENV['LINE_RANGE'].split('-')
    range = range_start..range_stop
    c.filter_run_including line_number: lambda do |line_number|
      range.include?(number)
    end
  end
end

With that in place, you could run rspec like so:

$ LINE_RANGE=10-15 rspec path/to/spec.rb

Let me know if that doesn't work for you.

Thanks for your response!

Good point, flags probably aren't workable. What about an expansion on the :num syntax, maybe file_name.rb:10,15 or file_name.rb:10-15? I think that maintaining fuzzy line number matching would be the intuitive behavior, so I don't see a problem there.

I gave that code a try but it didn't work for me; I appreciate the suggestion and I'll play with it more later. The idea is cool, though a more portable solution would be great, so that I could easily run specs in a line range on shared computers, pairs' computers, etc. Also, I wouldn't be able to permanently modify spec_helper.rb in this way on work or OSS projects.

You could use this as a basis for building this functionality into an extension gem, though.

In general, we don't want to increase the CLI surface area for features only requested by a small number of users, and you're the first to ask for this. Implementing this in RSpec correctly for all cases in a way that plays well with all features will not be as simple as you might expect, and I think an extension gem is likely the way to go on this.

What didn't work about the snippet?

OK, makes total sense.

Does the snippet work for you? It seemed like there were a couple syntaxy things, but after tweaking the code it still wasn't working for me. I'll take a longer look later. But I think I'll just end up solving this with a Vim function, that would probably be the most portable thing for me besides a change to rspec-core itself.

Here's a fixed version:

RSpec.configure do |c|
  if ENV['LINE_RANGE']
    range_start, range_stop = ENV['LINE_RANGE'].split('-')
    range = Integer(range_start)..Integer(range_stop)
    c.filter_run_including line_number: lambda { |line_number| range.include?(line_number) }
  end
end

I hadn't actually tried the snippet before (I just typed it in the github comment box), so I made a few dumb mistakes (like forgetting to convert the start/stop to integers). I've confirmed this snippet works, though.

Cool, thanks.

Was this page helpful?
0 / 5 - 0 ratings