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

Followups from #2065. #2105

Merged
merged 1 commit into from
Nov 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Enhancements:
(Yuji Nakayama, #2083)
* Add `max_displayed_failure_line_count` configuration option
(defaults to 10). (Yuji Nakayama, #2083)
* Enhance `fail_fast` option so it can take a number (e.g. `--fail-fast=3`)
to force the run to abort after the specified number of failures.
(Jack Scotti, #2065)

Bug Fixes:

Expand Down
2 changes: 1 addition & 1 deletion features/configuration/fail_fast.feature
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Feature: fail fast

Use the `fail_fast` option to tell RSpec to abort the run on after N failures:
Use the `fail_fast` option to tell RSpec to abort the run after N failures:

Scenario: `fail_fast` with no failures (runs all examples)
Given a file named "spec/spec_helper.rb" with:
Expand Down
2 changes: 1 addition & 1 deletion lib/rspec/core/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def only_failures_but_not_configured?

# @macro add_setting
# If specified, indicates the number of failures required before cleaning
# up and exit (default: `false`).
# up and exit (default: `nil`).
add_setting :fail_fast

# @macro add_setting
Expand Down
9 changes: 2 additions & 7 deletions lib/rspec/core/example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -547,8 +547,8 @@ def self.run(reporter=RSpec::Core::NullReporter)
for_filtered_examples(reporter) { |example| example.skip_with_exception(reporter, ex) }
true
rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
RSpec.world.wants_to_quit = true if fail_fast?
for_filtered_examples(reporter) { |example| example.fail_with_exception(reporter, ex) }
RSpec.world.wants_to_quit = true if reporter.fail_fast_limit_met?
false
ensure
run_after_context_hooks(new('after(:context) hook')) if should_run_context_hooks
Expand Down Expand Up @@ -579,7 +579,7 @@ def self.run_examples(reporter)
instance = new(example.inspect_output)
set_ivars(instance, before_context_ivars)
succeeded = example.run(instance, reporter)
if !succeeded && fail_fast? && reporter.fail_fast_limit_met?
if !succeeded && reporter.fail_fast_limit_met?
RSpec.world.wants_to_quit = true
end
succeeded
Expand All @@ -598,11 +598,6 @@ def self.for_filtered_examples(reporter, &block)
false
end

# @private
def self.fail_fast?
RSpec.configuration.fail_fast?
end

# @private
def self.declaration_line_numbers
@declaration_line_numbers ||= [metadata[:line_number]] +
Expand Down
2 changes: 1 addition & 1 deletion lib/rspec/core/option_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def parser(options)
begin
value = Integer(argument)
rescue ArgumentError
RSpec.warning "Non integer specified as fail count."
RSpec.warning "Expected an integer value for `--fail-fast`, got: #{argument.inspect}", :call_site => nil
end
end
set_fail_fast(options, value)
Expand Down
13 changes: 7 additions & 6 deletions lib/rspec/core/reporter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,13 @@ def abort_with(msg, exit_status)

# @private
def fail_fast_limit_met?
failures_required <= @failed_examples.size
end
return false unless (fail_fast = @configuration.fail_fast)

# @private
def failures_required
@configuration.fail_fast == true ? 1 : @configuration.fail_fast
if fail_fast == true
@failed_examples.any?
else
fail_fast <= @failed_examples.size
end
end

private
Expand All @@ -216,7 +217,7 @@ def close
def mute_profile_output?
# Don't print out profiled info if there are failures and `--fail-fast` is
# used, it just clutters the output.
[email protected]_examples? || (@configuration.fail_fast? && @failed_examples.size > 0)
[email protected]_examples? || fail_fast_limit_met?
end

def seed_used?
Expand Down
6 changes: 6 additions & 0 deletions spec/rspec/core/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ module RSpec::Core
end
end

describe "#fail_fast" do
it "defaults to `nil`" do
expect(RSpec::Core::Configuration.new.fail_fast).to be(nil)
end
end

describe '#deprecation_stream' do
it 'defaults to standard error' do
expect($rspec_core_without_stderr_monkey_patch.deprecation_stream).to eq STDERR
Expand Down
72 changes: 42 additions & 30 deletions spec/rspec/core/example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1233,8 +1233,7 @@ def extract_execution_results(group)
end

describe "#run_examples" do

let(:reporter) { double("reporter").as_null_object }
let(:reporter) { RSpec::Core::NullReporter }

it "returns true if all examples pass" do
group = RSpec.describe('group') do
Expand Down Expand Up @@ -1342,19 +1341,27 @@ def extract_execution_results(group)
end

describe "#run" do
context "with `fail_fast` set to `nil`" do
before { RSpec.configuration.fail_fast = nil }
let(:group) { RSpec.describe }
let(:reporter) { Reporter.new(RSpec.configuration) }

context "with fail_fast and failures_required == 1" do
let(:group) do
group = RSpec.describe
allow(group).to receive(:fail_fast?) { true }
group
end
let(:config) { Configuration.new }
let(:reporter) do
the_reporter = Reporter.new config
allow(the_reporter).to receive(:failures_required) { 1 }
the_reporter
it "does not run abort due to failures" do
examples_run = []
group().example('example 1') { examples_run << self; fail }
group().example('example 2') { examples_run << self; fail }
group().example('example 3') { examples_run << self; fail }

group().run(reporter)

expect(examples_run.length).to eq(3)
end
end

context "with fail_fast enabled" do
before { RSpec.configuration.fail_fast = true }
let(:group) { RSpec.describe }
let(:reporter) { Reporter.new(RSpec.configuration) }

it "does not run examples after the failed example" do
examples_run = []
Expand All @@ -1370,24 +1377,15 @@ def extract_execution_results(group)
it "sets RSpec.world.wants_to_quit flag if encountering an exception in before(:all)" do
group().before(:all) { raise "error in before all" }
group().example("equality") { expect(1).to eq(2) }
expect(group().run).to be_falsey
expect(group().run(reporter)).to be_falsey
expect(RSpec.world.wants_to_quit).to be_truthy
end
end

context "with fail_fast and failures_required = 3" do
let(:group) do
group = RSpec.describe
allow(group).to receive(:fail_fast?) { true }
group
end
let(:config) { Configuration.new }

let(:reporter) do
the_reporter = Reporter.new config
allow(the_reporter).to receive(:failures_required) { 3 }
the_reporter
end
context "with fail_fast set to 3" do
before { RSpec.configuration.fail_fast = 3 }
let(:group) { RSpec.describe }
let(:reporter) { Reporter.new(RSpec.configuration) }

it "does not run examples after 3 failed examples" do
examples_run = []
Expand All @@ -1402,11 +1400,25 @@ def extract_execution_results(group)
expect(examples_run.length).to eq(4)
end

it "sets RSpec.world.wants_to_quit flag if encountering an exception in before(:all)" do
it "does not set RSpec.world.wants_to_quit flag if encountering an exception in before(:all) causing less than 3 failures" do
group().before(:all) { raise "error in before all" }
group().example("equality") { expect(1).to eq(2) }
expect(group().run).to be_falsey
expect(RSpec.world.wants_to_quit).to be_truthy
group().example("equality") { expect(1).to eq(2) }

expect(group().run(reporter)).to be false

expect(RSpec.world.wants_to_quit).to be_falsey
end

it "sets RSpec.world.wants_to_quit flag if encountering an exception in before(:all) causing at least 3 failures" do
group().before(:all) { raise "error in before all" }
group().example("equality") { expect(1).to eq(1) }
group().example("equality") { expect(1).to eq(1) }
group().example("equality") { expect(1).to eq(1) }

expect(group().run(reporter)).to be false

expect(RSpec.world.wants_to_quit).to be true
end
end

Expand Down
4 changes: 1 addition & 3 deletions spec/rspec/core/option_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,7 @@ def generate_help_text

describe '--fail-fast' do
it 'warns when a non-integer is specified as fail count' do
expect(::Kernel).to receive(:warn) do |message|
expect(message).to match "Non integer specified as fail count"
end
expect_warning_without_call_site a_string_including("--fail-fast", "three")
Parser.parse(%w[--fail-fast=three])
end
end
Expand Down
17 changes: 0 additions & 17 deletions spec/rspec/core/reporter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -279,22 +279,5 @@ module RSpec::Core
reporter.finish
end
end

describe "#failures_required" do
it "returns 1 when RSpec.configuration.fail_fast == true" do
config.fail_fast = true
expect(reporter.failures_required).to eq 1
end

it "returns 1 when RSpec.configuration.fail_fast == 1" do
config.fail_fast = 1
expect(reporter.failures_required).to eq 1
end

it "returns RSpec.configuration.fail_fast when RSpec.configuration.fail_fast > 1" do
config.fail_fast = 3
expect(reporter.failures_required).to eq 3
end
end
end
end