You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fixture scope "package" wrong teardown order with nested packages #11480
When I run the tests I would expect the package_1 teardown to happen before setup of package_2, but this is not what is happening. Instead, teardown happens at the end. See output:
But when I move the test file out of the nested_dir so the file structure looks like this:
the teardown order seems to be correct.
Anyways I would love to have a correct teardown order for nested tests file structure.
I analyzed a little bit your case and here are my conclusions.
The Theory
The first step in executing a test suite with pytest implies the gathering of a list of each test method/function that must be called, and store them in a list named items in the order they are found.
Test Hooks
For each item in the items list, 3 hooks are executed:
pytest_runtest_setup
pytest_runtest_call
pytest_runtest_teardown
The 1st hook
During the pytest_runtest_setup hook, the fixtures are initialized in the following order:
Session's fixtures
Package's fixtures
Module's fixtures
Method's fixtures
The fixture is initialized at the step 4 (Method's fixtures), not sure why.
Note: In the pytest_runtest_setup hook, the session step is executed only for the first item.
The 2nd hook
The pytest_runtest_call hook is not really relevant for your problem, so on brief, this one just executes the test method/function.
The 3rd hook
Finally, in the pytest_runtest_teardown hook, the fixtures are teardown in the reverse order:
Method's fixtures
Module's fixtures
Package's fixtures
Session's fixtures
This time, the teardown of the fixture is not executed at the method's layer, instead it's executed at the package's layer.
Note: In the pytest_runtest_teardown hook, the session step is executed only for the last item.
Examples
Now, let's use your examples to highlight what's going on.
Example 1: test file in the same package as conftest
items = [Func test_1. Func test_2]
Apply the hooks on Func test_1
pytest_runtest_setup:
Session: nothing
package_1 = nothing
test_package_1.py = nothing
test_1 = Setup package 1
pytest_runtest_teardown:
test_1 = nothing
test_package_1.py = nothing
package_1 = Teardown package 1
Apply the hooks on Func test_2:
pytest_runtest_setup:
package_2 = nothing
test_package_2.py = nothing
test_2 = Setup package 2
pytest_runtest_teardown:
test_2 = nothing
test_package_2.py = nothing
package_2 = Teardown package 2
Session: nothing
So everything was good, because each test was in the same package as the used conftest.
Example 2: test file in a subpackage of conftest's package
items = [Func test_1. Func test_2]
Apply the hooks on Func test_1
pytest_runtest_setup:
Session: nothing
nested_dir = nothing
test_package_1.py = nothing
test_1 = Setup package 1
pytest_runtest_teardown:
test_1 = nothing
test_package_1.py = nothing
nested_dir = nothing
Apply the hooks on Func test_2:
pytest_runtest_setup:
package_2 = nothing
test_package_2.py = nothing
test_2 = Setup package 2
pytest_runtest_teardown:
test_2 = nothing
test_package_2.py = nothing
package_2 = Teardown package 2
Session: Teardown package 1
As you can see, the conftest is in the package_1, not in nested_dir. Meaning that the teardown of Func test_1 never goes to package_1. Thus, the teardown of the conftest from package_1 will be managed in the session's teardown, which is executed in the last item from the list.
Solution
The most obvious solution would be to include all the parent packages in the stack, such that the nodes of the Func test_1 to be [Session, package_1, nested_dir, test_package_1, test_1], instead of just [Session, nested_dir, test_package_1, test_1].
Unfortunately, this could impact other areas, so it's better if a contributor could share their opinion about this.
This is fixed by #11646, will will be included in pytest 8.0.0. The fix is as @robert-iancu-jr said -- now the Dir is nested under the Package. You can test the release candidate with pip install pytest==8.0.0rc1.
Activity
robert-iancu-jr commentedon Oct 10, 2023
Hello Dominik,
I analyzed a little bit your case and here are my conclusions.
The Theory
The first step in executing a test suite with pytest implies the gathering of a list of each test method/function that must be called, and store them in a list named
itemsin the order they are found.Test Hooks
For each item in the items list, 3 hooks are executed:
pytest_runtest_setuppytest_runtest_callpytest_runtest_teardownThe 1st hook
During the
pytest_runtest_setuphook, the fixtures are initialized in the following order:The fixture is initialized at the step 4 (Method's fixtures), not sure why.
Note: In the
pytest_runtest_setuphook, the session step is executed only for the first item.The 2nd hook
The
pytest_runtest_callhook is not really relevant for your problem, so on brief, this one just executes the test method/function.The 3rd hook
Finally, in the
pytest_runtest_teardownhook, the fixtures are teardown in the reverse order:This time, the teardown of the fixture is not executed at the method's layer, instead it's executed at the package's layer.
Note: In the
pytest_runtest_teardownhook, the session step is executed only for the last item.Examples
Now, let's use your examples to highlight what's going on.
Example 1: test file in the same package as conftest
items = [Func test_1. Func test_2]Apply the hooks on
Func test_1Apply the hooks on
Func test_2:So everything was good, because each test was in the same package as the used conftest.
Example 2: test file in a subpackage of conftest's package
items = [Func test_1. Func test_2]Apply the hooks on
Func test_1Apply the hooks on
Func test_2:As you can see, the conftest is in the package_1, not in nested_dir. Meaning that the teardown of
Func test_1never goes to package_1. Thus, the teardown of the conftest from package_1 will be managed in the session's teardown, which is executed in the last item from the list.Solution
The most obvious solution would be to include all the parent packages in the stack, such that the nodes of the
Func test_1to be[Session, package_1, nested_dir, test_package_1, test_1], instead of just[Session, nested_dir, test_package_1, test_1].Unfortunately, this could impact other areas, so it's better if a contributor could share their opinion about this.
bluetech commentedon Jan 4, 2024
This is fixed by #11646, will will be included in pytest 8.0.0. The fix is as @robert-iancu-jr said -- now the Dir is nested under the Package. You can test the release candidate with
pip install pytest==8.0.0rc1.