Skip to content

Commit

Permalink
Make sure nested at_exit blocks don't break exit status
Browse files Browse the repository at this point in the history
Per teamcapybara/capybara#178, it's possible
to have at_exit handlers installed inside Runner's run method that
execute after the 'exit' call in autorun. These at_exit handlers
can actually change the exit status (in this case, manual testing
reveals that capybara's call to @browser.quit in driver.rb seems to
be the problem).

Avoid this issue entirely by isolating the at_exit handler that calls
exit, ensuring it can't nest at_exit handlers.
  • Loading branch information
Travis Vachon committed Jun 3, 2011
1 parent 3db6c4c commit c24caf6
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
16 changes: 15 additions & 1 deletion features/command_line/exit_status.feature
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,25 @@ Feature: exit status
When I run `rspec nested_ko_spec.rb`
Then the exit status should be 1
And the output should contain "1 example, 1 failure"

Scenario: exit with 0 when no examples are run
Given a file named "a_no_examples_spec.rb" with:
"""
"""
When I run `rspec a_no_examples_spec.rb`
Then the exit status should be 0
And the output should contain "0 examples"

Scenario: exit with 1 when one example fails even if a nested exit handler calls exit(0)
Given a file named "ko_with_exit_handler_spec.rb" with:
"""
describe "KO" do
it "fails" do
at_exit { exit(0) }
raise "KO"
end
end
"""
When I run `rspec ko_with_exit_handler_spec.rb`
Then the exit status should be 1
And the output should contain "1 example, 1 failure"
7 changes: 6 additions & 1 deletion lib/rspec/core/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ class Runner
def self.autorun
return if autorun_disabled? || installed_at_exit? || running_in_drb?
@installed_at_exit = true
at_exit { exit(run(ARGV, $stderr, $stdout).to_i) }
at_exit do
exit_status = 0
# make sure this one really runs last to ensure proper exit status
at_exit { exit(exit_status) }
exit_status = run(ARGV, $stderr, $stdout).to_i
end
end
AT_EXIT_HOOK_BACKTRACE_LINE = "#{__FILE__}:#{__LINE__ - 2}:in `autorun'"

Expand Down

0 comments on commit c24caf6

Please sign in to comment.