Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SetupAndTeardown#teardown should call any subsequent after_teardown: #32472

Merged
merged 2 commits into from
Apr 6, 2018

Conversation

Edouard-chin
Copy link
Member

SetupAndTeardown#teardown should call any subsequent after_teardown:

If you have a regular test that have a teardown block, and for any reason an exception get raised,
ActiveSupport will not run subsequent after_teardown method provided by other module or gems.
One of them being the ActiveRecord::TestFixtures which won't rollback the transation when the test
ends making all subsequent test to be in a weird state.

The default implementation of minitest is to run all teardown methods from the user's test, rescue all
exceptions, run all after_teardown methods provided by libraries and finally re-raise the exception
that happened in the user's teardown method.
Rails should do the same.

@rails-bot
Copy link

r? @pixeltrix

(@rails-bot has picked a reviewer for you, use r? to override)

  If you have a regular test that have a teardown block, and for any reason an exception get raised, ActiveSupport will not run subsequent after_teardown method provided by other module or gems.
  One of them being the ActiveRecord::TestFixtures which won't rollback the transation when the test ends making all subsequent test to be in a weird state.

  The default implementation of minitest is to run all teardown methods from the user's test, rescue all exceptions, run all after_teardown methods provided by libraries and finally re-raise the exception that happened in the user's teardown method.
  Rails should do the same.
begin
run_callbacks :teardown
rescue => e
error = e
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if multiple teardown callbacks would raise?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first one would halt the execution of the others. Like it would happen if we were using def teardown instead of the teardown callback.

@kirs
Copy link
Member

kirs commented Apr 6, 2018

Rails should do the same.

👍 for doing the same as MiniTest.

Copy link
Member

@rafaelfranca rafaelfranca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not we do the same with before_setup?

begin
run_callbacks :teardown
rescue => e
error = e
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first one would halt the execution of the others. Like it would happen if we were using def teardown instead of the teardown callback.

@rafaelfranca
Copy link
Member

Oh, forget about it, before_setup runs after all other before_setup.

end
end

class SetupAndTeardownTest < Minitest::Test
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a class with the same name in activesupport/test/test_case_test.rb. We need to rename this class.

@rafaelfranca rafaelfranca merged commit 00f2dbd into rails:master Apr 6, 2018
rafaelfranca added a commit that referenced this pull request Apr 6, 2018
`SetupAndTeardown#teardown` should call any subsequent after_teardown:
rafaelfranca added a commit that referenced this pull request Apr 6, 2018
`SetupAndTeardown#teardown` should call any subsequent after_teardown:
@Edouard-chin Edouard-chin deleted the ec-activesupport-teardown branch April 6, 2018 17:13
Edouard-chin added a commit to Edouard-chin/rails that referenced this pull request Apr 27, 2018
- In rails#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](https://github.com/rails/rails/blob/7d2400ab61c8e3ed95e14d03ba3844e8ba2e36e4/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
@Edouard-chin Edouard-chin mentioned this pull request Jan 30, 2024
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants