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

Commit e68d17f

Browse files
committed
Add --fail-no-examples option: fail if no RSpec examples
Default behavior not changed.
1 parent f81ff4a commit e68d17f

File tree

9 files changed

+147
-15
lines changed

9 files changed

+147
-15
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Feature: `--fail-no-examples` option
2+
3+
Use the `--fail-no-examples` option to make RSpec return non zero exit status
4+
when there are 0 examples.
5+
6+
Background:
7+
Given a file named "spec/spec_helper.rb" with:
8+
"""ruby
9+
RSpec.configure do |c|
10+
# no options here
11+
end
12+
"""
13+
14+
Scenario: A failing spec example
15+
Given a file named "example_spec.rb" with:
16+
"""ruby
17+
RSpec.describe "something" do
18+
it "fails" do
19+
fail
20+
end
21+
end
22+
"""
23+
When I run `rspec --fail-no-examples example_spec.rb`
24+
Then the exit status should be 1
25+
26+
Scenario: A passing spec example
27+
Given a file named "example_spec.rb" with:
28+
"""ruby
29+
require 'spec_helper'
30+
RSpec.describe "something" do
31+
it "succeeds" do
32+
true
33+
end
34+
end
35+
"""
36+
When I run `rspec --fail-no-examples example_spec.rb`
37+
Then the exit status should be 0
38+
39+
Scenario: No examples
40+
Given a file named "example_spec.rb" with:
41+
"""ruby
42+
require 'spec_helper'
43+
RSpec.describe "something" do
44+
end
45+
"""
46+
When I run `rspec --fail-no-examples example_spec.rb`
47+
Then the exit status should be 1
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
Feature: fail no examples
2+
3+
Use the `fail_no_examples` option to make RSpec return non zero exit status
4+
when there are 0 examples.
5+
6+
```ruby
7+
RSpec.configure { |c| c.fail_no_examples = true }
8+
```
9+
10+
Background:
11+
Given a file named "spec/spec_helper.rb" with:
12+
"""ruby
13+
RSpec.configure { |c| c.fail_no_examples = true }
14+
"""
15+
16+
Scenario: A failing spec example
17+
Given a file named "spec/example_spec.rb" with:
18+
"""ruby
19+
RSpec.describe "something" do
20+
it "fails" do
21+
fail
22+
end
23+
end
24+
"""
25+
When I run `rspec spec/example_spec.rb`
26+
Then the exit status should be 1
27+
28+
Scenario: A passing spec example
29+
Given a file named "spec/example_spec.rb" with:
30+
"""ruby
31+
require 'spec_helper'
32+
RSpec.describe "something" do
33+
it "succeeds" do
34+
true
35+
end
36+
end
37+
"""
38+
When I run `rspec spec/example_spec.rb`
39+
Then the exit status should be 0
40+
41+
Scenario: No examples
42+
Given a file named "spec/example_spec.rb" with:
43+
"""ruby
44+
require 'spec_helper'
45+
RSpec.describe "something" do
46+
end
47+
"""
48+
When I run `rspec spec/example_spec.rb`
49+
Then the exit status should be 1

lib/rspec/core/configuration.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ def only_failures_but_not_configured?
199199
# The exit code to return if there are any failures (default: 1).
200200
add_setting :failure_exit_code
201201

202+
# @macro add_setting
203+
# Whether or not to fail when there are no RSpec examples (default: false).
204+
add_setting :fail_no_examples
205+
202206
# @macro define_reader
203207
# Indicates files configured to be required.
204208
define_reader :requires
@@ -425,6 +429,7 @@ def initialize
425429
@pattern = '**{,/*/**}/*_spec.rb'
426430
@exclude_pattern = ''
427431
@failure_exit_code = 1
432+
@fail_no_examples = false
428433
@spec_files_loaded = false
429434

430435
@backtrace_formatter = BacktraceFormatter.new

lib/rspec/core/drb.rb

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@ def initialize(submitted_options, filter_manager)
4040

4141
def options
4242
argv = []
43-
argv << "--color" if @submitted_options[:color]
44-
argv << "--profile" if @submitted_options[:profile_examples]
45-
argv << "--backtrace" if @submitted_options[:full_backtrace]
46-
argv << "--tty" if @submitted_options[:tty]
47-
argv << "--fail-fast" if @submitted_options[:fail_fast]
48-
argv << "--options" << @submitted_options[:custom_options_file] if @submitted_options[:custom_options_file]
49-
argv << "--order" << @submitted_options[:order] if @submitted_options[:order]
43+
argv << "--color" if @submitted_options[:color]
44+
argv << "--profile" if @submitted_options[:profile_examples]
45+
argv << "--backtrace" if @submitted_options[:full_backtrace]
46+
argv << "--tty" if @submitted_options[:tty]
47+
argv << "--fail-fast" if @submitted_options[:fail_fast]
48+
argv << "--fail-no-examples" if @submitted_options[:fail_no_examples]
49+
argv << "--options" << @submitted_options[:custom_options_file] if @submitted_options[:custom_options_file]
50+
argv << "--order" << @submitted_options[:order] if @submitted_options[:order]
5051

5152
add_failure_exit_code(argv)
5253
add_full_description(argv)

lib/rspec/core/option_parser.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ def parser(options)
9393
options[:failure_exit_code] = code
9494
end
9595

96+
parser.on('--fail-no-examples', 'Whether or not to fail when there are'\
97+
' no RSpec examples. Defaults to `false`.') do |_o|
98+
options[:fail_no_examples] = true
99+
end
100+
96101
parser.on('--dry-run', 'Print the formatter output of your suite without',
97102
' running any examples or hooks') do |_o|
98103
options[:dry_run] = true

lib/rspec/core/rake_task.rb

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@ class RakeTask < ::Rake::TaskLib
3838
# Defaults to `nil`.
3939
attr_accessor :exclude_pattern
4040

41-
# Whether or not to fail Rake when an error occurs (typically when
41+
# Whether or not to fail Rake task when an error occurs (typically when
4242
# examples fail). Defaults to `true`.
4343
attr_accessor :fail_on_error
4444

45+
# Whether or not to fail Rake task when there are no RSpec examples.
46+
# Defaults to `false`.
47+
attr_accessor :fail_no_examples
48+
4549
# A message to print to stderr when there are failures.
4650
attr_accessor :failure_message
4751

@@ -60,13 +64,14 @@ class RakeTask < ::Rake::TaskLib
6064
attr_accessor :rspec_opts
6165

6266
def initialize(*args, &task_block)
63-
@name = args.shift || :spec
64-
@ruby_opts = nil
65-
@rspec_opts = nil
66-
@verbose = true
67-
@fail_on_error = true
68-
@rspec_path = DEFAULT_RSPEC_PATH
69-
@pattern = DEFAULT_PATTERN
67+
@name = args.shift || :spec
68+
@ruby_opts = nil
69+
@rspec_opts = nil
70+
@verbose = true
71+
@fail_on_error = true
72+
@fail_no_examples = false
73+
@rspec_path = DEFAULT_RSPEC_PATH
74+
@pattern = DEFAULT_PATTERN
7075

7176
define(args, &task_block)
7277
end

lib/rspec/core/runner.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ def setup(err, out)
110110
def run_specs(example_groups)
111111
@configuration.reporter.report(@world.example_count(example_groups)) do |reporter|
112112
@configuration.with_suite_hooks do
113+
if @world.example_count(example_groups) == 0 && @configuration.fail_no_examples
114+
return 1
115+
end
113116
example_groups.map { |g| g.run(reporter) }.all? ? 0 : @configuration.failure_exit_code
114117
end
115118
end

spec/rspec/core/configuration_options_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,16 @@
296296
end
297297
end
298298

299+
describe "--fail-no-examples" do
300+
it "defaults to false" do
301+
expect(parse_options[:fail_no_examples]).to be_falsey
302+
end
303+
304+
it "sets fail_no_examples on config" do
305+
expect(parse_options("--fail-no-examples")[:fail_no_examples]).to be_truthy
306+
end
307+
end
308+
299309
describe "--dry-run" do
300310
it "defaults to false" do
301311
expect(parse_options[:dry_run]).to be_falsey

spec/rspec/core/rake_task_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ def silence_output(&block)
112112
end
113113
end
114114

115+
context 'with --fail-no-examples set' do
116+
it 'adds the rspec_opts' do
117+
task.rspec_opts = "--fail-no-examples"
118+
expect(spec_command).to match(/#{task.rspec_path}.*--fail-no-examples/)
119+
end
120+
end
121+
115122
context 'with verbose enabled' do
116123
it 'prints the command only to stdout for passing specs', :slow do
117124
expect {

0 commit comments

Comments
 (0)