Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit ef17239

Browse files
tansakuJonRowe
authored andcommitted
Add support for --example-matches
Add support for --example-matches / -E that allows matching examples with regex syntax, fixes #2584
1 parent cb1b4ce commit ef17239

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
Feature: `--example-matches` option
2+
3+
Use the `--example-matches` (or `-E`) option to filter examples by name using REGEX.
4+
5+
The argument is matched against the full description of the example, which is
6+
the concatenation of descriptions of the group (including any nested groups)
7+
and the example.
8+
9+
This allows you to run a single uniquely named example, all examples with
10+
similar names, all the examples in a uniquely named group, etc, etc.
11+
12+
You can also use the option more than once to specify multiple example
13+
matches.
14+
15+
Note: description-less examples that have generated descriptions (typical when using the [one-liner syntax](../subject/one-liner-syntax)) cannot be directly filtered with this option, because it is necessary to execute the example to generate the description, so RSpec is unable to use the not-yet-generated description to decide whether or not to execute an example. You can, of course, pass part of a group's description to select all examples defined in the group (including those that have no description).
16+
17+
Background:
18+
Given a file named "first_spec.rb" with:
19+
"""ruby
20+
RSpec.describe "first group" do
21+
it "first" do; end
22+
it "first example in first group" do; end
23+
it "second example in first group" do; end
24+
end
25+
"""
26+
And a file named "second_spec.rb" with:
27+
"""ruby
28+
RSpec.describe "second group" do
29+
it "first example in second group" do; end
30+
it "second example in second group" do; end
31+
end
32+
"""
33+
And a file named "third_spec.rb" with:
34+
"""ruby
35+
RSpec.describe "third group" do
36+
it "first example in third group" do; end
37+
context "group of nest" do
38+
it "first example in nested group" do; end
39+
it "second example in nested group" do; end
40+
it "third example in nested_group with underscore" do; end
41+
end
42+
end
43+
"""
44+
And a file named "fourth_spec.rb" with:
45+
"""ruby
46+
RSpec.describe Array do
47+
describe "#length" do
48+
it "is the number of items" do
49+
expect(Array.new([1,2,3]).length).to eq 3
50+
end
51+
end
52+
end
53+
"""
54+
55+
Scenario: No matches
56+
When I run `rspec . --example-matches nothing_like_this`
57+
Then the process should succeed even though no examples were run
58+
59+
Scenario: Match on one word
60+
When I run `rspec . --example-matches example`
61+
Then the examples should all pass
62+
63+
Scenario: One match in each context
64+
When I run `rspec . --example-matches 'first example'`
65+
Then the examples should all pass
66+
67+
Scenario: One match in one file using just the example name
68+
When I run `rspec . --example-matches 'first example in first group'`
69+
Then the examples should all pass
70+
71+
Scenario: One match in one file using the example name and the group name
72+
When I run `rspec . --example-matches 'first group first example in first group'`
73+
Then the examples should all pass
74+
75+
Scenario: All examples in one group
76+
When I run `rspec . --example-matches 'first group'`
77+
Then the examples should all pass
78+
79+
Scenario: One match in one file with group name
80+
When I run `rspec . --example-matches 'second group first example'`
81+
Then the examples should all pass
82+
83+
Scenario: All examples in one group including examples in nested groups
84+
When I run `rspec . --example-matches 'third group'`
85+
Then the examples should all pass
86+
87+
Scenario: Match using `ClassName#method_name` form
88+
When I run `rspec . --example-matches 'Array#length'`
89+
Then the examples should all pass
90+
91+
Scenario: Match only matching regex
92+
When I run `rspec . --example-matches "first$" --format d`
93+
Then the examples should all pass
94+
And the output should contain all of these:
95+
| first |
96+
And the output should not contain any of these:
97+
| first example in first group |
98+
| second example in first group |
99+
| first example in second group |
100+
| second example in second group |
101+
| first example in third group |
102+
| nested group first example in nested group |
103+
| nested group second example in nested group |
104+
105+
# https://regex101.com/r/RABd8Q/2
106+
Scenario: Match only matching regex with word boundarries
107+
When I run `rspec . --example-matches "nested[^_]" --format d`
108+
Then the examples should all pass
109+
And the output should contain all of these:
110+
| first example in nested group |
111+
| second example in nested group |
112+
And the output should not contain any of these:
113+
| first example in first group |
114+
| second example in first group |
115+
| first example in second group |
116+
| second example in second group |
117+
| first example in third group |
118+
| third example in nested_group |
119+
120+
Scenario: Multiple applications of example name option
121+
When I run `rspec . --example-matches 'first group' --example-matches 'second group' --format d`
122+
Then the examples should all pass
123+
And the output should contain all of these:
124+
| first example in first group |
125+
| second example in first group |
126+
| first example in second group |
127+
| second example in second group |
128+
And the output should not contain any of these:
129+
| first example in third group |
130+
| nested group first example in nested group |
131+
| nested group second example in nested group |

lib/rspec/core/option_parser.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def parse(source=nil)
3737
# rubocop:disable Metrics/AbcSize
3838
# rubocop:disable CyclomaticComplexity
3939
# rubocop:disable PerceivedComplexity
40+
# rubocop:disable Metrics/BlockLength
4041
def parser(options)
4142
OptionParser.new do |parser|
4243
parser.summary_width = 34
@@ -226,6 +227,11 @@ def parser(options)
226227
(options[:full_description] ||= []) << Regexp.compile(Regexp.escape(o))
227228
end
228229

230+
parser.on('-E', '--example-matches REGEX', "Run examples whose full nested names match REGEX (may be",
231+
" used more than once)") do |o|
232+
(options[:full_description] ||= []) << Regexp.compile(o)
233+
end
234+
229235
parser.on('-t', '--tag TAG[:VALUE]',
230236
'Run examples with the specified tag, or exclude examples',
231237
'by adding ~ before the tag.',
@@ -288,6 +294,7 @@ def parser(options)
288294
end
289295
end
290296
end
297+
# rubocop:enable Metrics/BlockLength
291298
# rubocop:enable Metrics/AbcSize
292299
# rubocop:enable MethodLength
293300
# rubocop:enable CyclomaticComplexity

spec/rspec/core/option_parser_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@ module RSpec::Core
216216
end
217217
end
218218

219+
%w[--example-matches -E].each do |option|
220+
describe option do
221+
it "does not escape the arg" do
222+
options = Parser.parse([option, 'this (and that)\b'])
223+
expect(options[:full_description].length).to eq(1)
224+
expect(/this (and that)\b/).to eq(options[:full_description].first)
225+
end
226+
end
227+
end
228+
219229
%w[--pattern -P].each do |option|
220230
describe option do
221231
it "sets the filename pattern" do

0 commit comments

Comments
 (0)