-
-
Notifications
You must be signed in to change notification settings - Fork 753
Handle errors in :suite hooks. #2316
Changes from 6 commits
a1936ff
de49f81
ebbea9f
fd4e761
5ae27f2
77f8b01
bef9d61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -151,6 +151,18 @@ def deprecation(hash) | |
notify :deprecation, Notifications::DeprecationNotification.from_hash(hash) | ||
end | ||
|
||
# @private | ||
# Provides a way to notify of an exception that is not tied to any | ||
# particular exception (such as an exception encountered in a :suite hook). | ||
# Exceptions will be formatted the same way they normally are. | ||
def notify_non_example_exception(exception, context_description) | ||
@configuration.world.non_example_failure = true | ||
|
||
example = Example.new(AnonymousExampleGroup, context_description, {}) | ||
presenter = Formatters::ExceptionPresenter.new(exception, example, :indentation => 0) | ||
message presenter.fully_formatted(nil) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just double checking that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
end | ||
|
||
# @private | ||
def finish | ||
close_after do | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,14 +109,17 @@ def setup(err, out) | |
# failed. | ||
def run_specs(example_groups) | ||
examples_count = @world.example_count(example_groups) | ||
@configuration.reporter.report(examples_count) do |reporter| | ||
success = @configuration.reporter.report(examples_count) do |reporter| | ||
@configuration.with_suite_hooks do | ||
if examples_count == 0 && @configuration.fail_if_no_examples | ||
return @configuration.failure_exit_code | ||
end | ||
example_groups.map { |g| g.run(reporter) }.all? ? 0 : @configuration.failure_exit_code | ||
|
||
example_groups.map { |g| g.run(reporter) }.all? | ||
end | ||
end | ||
end && [email protected]_example_failure | ||
|
||
success ? 0 : @configuration.failure_exit_code | ||
end | ||
|
||
private | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
require 'support/aruba_support' | ||
require 'support/formatter_support' | ||
|
||
RSpec.describe 'Suite hook errors' do | ||
include_context "aruba support" | ||
include FormatterSupport | ||
|
||
let(:failure_exit_code) { rand(97) + 2 } # 2..99 | ||
|
||
if RSpec::Support::Ruby.jruby_9000? | ||
let(:spec_line_suffix) { ":in `block in (root)'" } | ||
elsif RSpec::Support::Ruby.jruby? | ||
let(:spec_line_suffix) { ":in `(root)'" } | ||
elsif RUBY_VERSION == "1.8.7" | ||
let(:spec_line_suffix) { "" } | ||
else | ||
let(:spec_line_suffix) { ":in `block (2 levels) in <top (required)>'" } | ||
end | ||
|
||
before do | ||
# get out of `aruba` sub-dir so that `filter_gems_from_backtrace 'aruba'` | ||
# below does not filter out our spec file. | ||
expect(dirs.pop).to eq "aruba" | ||
|
||
clean_current_dir | ||
|
||
RSpec.configure do |c| | ||
c.filter_gems_from_backtrace "aruba" | ||
c.backtrace_exclusion_patterns << %r{/rspec-core/spec/} << %r{rspec_with_simplecov} | ||
c.failure_exit_code = failure_exit_code | ||
end | ||
end | ||
|
||
def run_spec_expecting_non_zero(before_or_after) | ||
write_file "the_spec.rb", " | ||
RSpec.configure do |c| | ||
c.#{before_or_after}(:suite) do | ||
raise 'boom' | ||
end | ||
end | ||
|
||
RSpec.describe do | ||
it { } | ||
end | ||
" | ||
|
||
run_command "the_spec.rb" | ||
expect(last_cmd_exit_status).to eq(failure_exit_code) | ||
normalize_durations(last_cmd_stdout) | ||
end | ||
|
||
it 'nicely formats errors in `before(:suite)` hooks and exits with non-zero' do | ||
output = run_spec_expecting_non_zero(:before) | ||
expect(output).to eq unindent(<<-EOS) | ||
|
||
An error occurred in a `before(:suite)` hook. | ||
Failure/Error: raise 'boom' | ||
|
||
RuntimeError: | ||
boom | ||
# ./the_spec.rb:4#{spec_line_suffix} | ||
|
||
|
||
Finished in n.nnnn seconds (files took n.nnnn seconds to load) | ||
0 examples, 0 failures | ||
EOS | ||
end | ||
|
||
it 'nicely formats errors in `after(:suite)` hooks and exits with non-zero' do | ||
output = run_spec_expecting_non_zero(:after) | ||
expect(output).to eq unindent(<<-EOS) | ||
. | ||
An error occurred in an `after(:suite)` hook. | ||
Failure/Error: raise 'boom' | ||
|
||
RuntimeError: | ||
boom | ||
# ./the_spec.rb:4#{spec_line_suffix} | ||
|
||
|
||
Finished in n.nnnn seconds (files took n.nnnn seconds to load) | ||
1 example, 0 failures | ||
EOS | ||
end | ||
|
||
it 'nicely formats errors from multiple :suite hooks of both types and exits with non-zero' do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. huh this is interesting: we keep running hooks even if one fails. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was a good point. In the follow-up commit I just pushed I addressed this, and made it behave the same as |
||
write_file "the_spec.rb", " | ||
RSpec.configure do |c| | ||
c.before(:suite) { raise 'before 1' } | ||
c.before(:suite) { raise 'before 2' } | ||
c.after(:suite) { raise 'after 1' } | ||
c.after(:suite) { raise 'after 2' } | ||
end | ||
|
||
RSpec.describe do | ||
it { } | ||
end | ||
" | ||
|
||
run_command "the_spec.rb" | ||
expect(last_cmd_exit_status).to eq(failure_exit_code) | ||
output = normalize_durations(last_cmd_stdout) | ||
|
||
expect(output).to eq unindent(<<-EOS) | ||
|
||
An error occurred in a `before(:suite)` hook. | ||
Failure/Error: c.before(:suite) { raise 'before 1' } | ||
|
||
RuntimeError: | ||
before 1 | ||
# ./the_spec.rb:3#{spec_line_suffix} | ||
|
||
An error occurred in a `before(:suite)` hook. | ||
Failure/Error: c.before(:suite) { raise 'before 2' } | ||
|
||
RuntimeError: | ||
before 2 | ||
# ./the_spec.rb:4#{spec_line_suffix} | ||
|
||
An error occurred in an `after(:suite)` hook. | ||
Failure/Error: c.after(:suite) { raise 'after 2' } | ||
|
||
RuntimeError: | ||
after 2 | ||
# ./the_spec.rb:6#{spec_line_suffix} | ||
|
||
An error occurred in an `after(:suite)` hook. | ||
Failure/Error: c.after(:suite) { raise 'after 1' } | ||
|
||
RuntimeError: | ||
after 1 | ||
# ./the_spec.rb:5#{spec_line_suffix} | ||
|
||
|
||
Finished in n.nnnn seconds (files took n.nnnn seconds to load) | ||
0 examples, 0 failures | ||
EOS | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First
exception
should readexample
I think?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, fixed.