mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
1cf8b6c231
- In #32472 I introduced a fix in order for all `after_teardown` method provided by libraries and Rails to run, even if the application's `teardown` method raised an error (That's the default minitest behavior). However this change wasn't enough and doesn't take in consideration the ancestors chain.
If a library's module containing an `after_teardown` method get included after the `SetupAndTeardown` module (one example is the [ActiveRecord::TestFixtures module](7d2400ab61/activerecord/lib/active_record/fixtures.rb (L855-L856)
), then the ancestors of the test class would look something like
```ruby
class MyTest < ActiveSupport::TestCase
end
puts MyTest.ancestors # [MyTest, ActiveSupport::TestCase, ActiveRecord::TestFixtures, ActiveSupport::Testing::SetupAndTeardown]
```
Any class/module in the ancestors chain that are **before** the `ActiveSupport::Testing::SetupAndTeardown` will behave incorrectly:
- Their `before_setup` method will get called **after** all regular setup method
- Their `after_teardown` method won't even get called in case an exception is raised inside a regular's test `teardown`
A simple reproduction script of the problem here https://gist.github.com/Edouard-chin/70705542a59a8593f619b02e1c0a188c
- One solution to this problem is to have the `AS::SetupAndTeardown` module be the very first in the ancestors chain. By doing that we ensure that no `before_setup` / `after_teardown` get executed prior to running the teardown callbacks
36 lines
647 B
Ruby
36 lines
647 B
Ruby
# frozen_string_literal: true
|
|
|
|
require "abstract_unit"
|
|
|
|
module OtherAfterTeardown
|
|
def after_teardown
|
|
super
|
|
|
|
@witness = true
|
|
end
|
|
end
|
|
|
|
class AfterTeardownTest < ActiveSupport::TestCase
|
|
include OtherAfterTeardown
|
|
|
|
attr_writer :witness
|
|
|
|
MyError = Class.new(StandardError)
|
|
|
|
teardown do
|
|
raise MyError, "Test raises an error, all after_teardown should still get called"
|
|
end
|
|
|
|
def after_teardown
|
|
assert_changes -> { failures.count }, from: 0, to: 1 do
|
|
super
|
|
end
|
|
|
|
assert_equal true, @witness
|
|
failures.clear
|
|
end
|
|
|
|
def test_teardown_raise_but_all_after_teardown_method_are_called
|
|
assert true
|
|
end
|
|
end
|