From 9e7dcd376157fcfe72b35b8a9b4fe5a8043d8b0c Mon Sep 17 00:00:00 2001 From: Myron Marston Date: Sat, 9 Oct 2010 16:45:31 -0700 Subject: [PATCH] Rescue errors in after(:all) and print them out. This isn't a good permanent solution, but it's better than the current behavior. Currently, RSpec's error handling raises its own error for an error in after(:all), which gives the user a confusing error message and hides the user's error message. --- features/hooks/before_and_after_hooks.feature | 23 ++++++++++++++++ lib/rspec/core/example_group.rb | 16 +++++++++++- spec/rspec/core/example_group_spec.rb | 26 +++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/features/hooks/before_and_after_hooks.feature b/features/hooks/before_and_after_hooks.feature index 453c00b220..0500ab5126 100644 --- a/features/hooks/before_and_after_hooks.feature +++ b/features/hooks/before_and_after_hooks.feature @@ -155,6 +155,29 @@ Feature: before and after hooks after all ran """ + Scenario: failure in after(:all) block + Given a file named "after_all_spec.rb" with: + """ + describe "an error in after(:all)" do + after(:all) do + raise StandardError.new("Boom!") + end + + it "passes this example" do + end + + it "passes this example, too" do + end + end + """ + When I run "rspec after_all_spec.rb" + Then the output should contain "2 examples, 0 failures" + And the output should contain: + """ + An error occurred in an after(:all) hook. + StandardError: Boom! + """ + Scenario: define before and after blocks in configuration Given a file named "befores_in_configuration_spec.rb" with: """ diff --git a/lib/rspec/core/example_group.rb b/lib/rspec/core/example_group.rb index 1cc4d63763..c872630929 100644 --- a/lib/rspec/core/example_group.rb +++ b/lib/rspec/core/example_group.rb @@ -198,7 +198,20 @@ def self.eval_after_eachs(example_group_instance) def self.eval_after_alls(example_group_instance) return if descendant_filtered_examples.empty? assign_before_all_ivars(before_all_ivars, example_group_instance) - run_hook!(:after, :all, example_group_instance) + + begin + run_hook!(:after, :all, example_group_instance) + rescue => e + # TODO: come up with a better solution for this. + RSpec.configuration.reporter.message <<-EOS + +An error occurred in an after(:all) hook. + #{e.class}: #{e.message} + occurred at #{e.backtrace.first} + + EOS + end + world.run_hook_filtered(:after, :all, self, example_group_instance) if top_level? end @@ -290,6 +303,7 @@ def instance_eval_with_rescue(&hook) begin instance_eval(&hook) rescue Exception => e + raise unless example example.set_exception(e) end end diff --git a/spec/rspec/core/example_group_spec.rb b/spec/rspec/core/example_group_spec.rb index a80c676eb2..a4e3c1407e 100644 --- a/spec/rspec/core/example_group_spec.rb +++ b/spec/rspec/core/example_group_spec.rb @@ -384,6 +384,32 @@ module RSpec::Core example.metadata[:execution_result][:exception_encountered].message.should == "error in before all" end + context "when an error occurs in an after(:all) hook" do + before(:each) do + RSpec.configuration.reporter.stub(:message) + end + + let(:group) do + ExampleGroup.describe do + after(:all) { raise "error in after all" } + it("equality") { 1.should == 1 } + end + end + + it "allows the example to pass" do + group.run + example = group.examples.first + example.metadata.should_not be_nil + example.metadata[:execution_result].should_not be_nil + example.metadata[:execution_result][:status].should == "passed" + end + + it "rescues the error and prints it out" do + RSpec.configuration.reporter.should_receive(:message).with(/error in after all/) + group.run + end + end + it "has no 'running example' within before(:all)" do group = ExampleGroup.describe running_example = :none