|
1 | 1 | """Run testsuites written for nose."""
|
2 |
| -from _pytest import python |
3 |
| -from _pytest import unittest |
4 | 2 | from _pytest.config import hookimpl
|
5 | 3 | from _pytest.fixtures import getfixturemarker
|
6 | 4 | from _pytest.nodes import Item
|
| 5 | +from _pytest.python import Function |
| 6 | +from _pytest.unittest import TestCaseFunction |
7 | 7 |
|
8 | 8 |
|
9 | 9 | @hookimpl(trylast=True)
|
10 |
| -def pytest_runtest_setup(item) -> None: |
11 |
| - if is_potential_nosetest(item): |
12 |
| - if not call_optional(item.obj, "setup"): |
13 |
| - # Call module level setup if there is no object level one. |
14 |
| - call_optional(item.parent.obj, "setup") |
15 |
| - # XXX This implies we only call teardown when setup worked. |
16 |
| - item.addfinalizer(lambda: teardown_nose(item)) |
17 |
| - |
18 |
| - |
19 |
| -def teardown_nose(item) -> None: |
20 |
| - if is_potential_nosetest(item): |
21 |
| - if not call_optional(item.obj, "teardown"): |
22 |
| - call_optional(item.parent.obj, "teardown") |
23 |
| - |
24 |
| - |
25 |
| -def is_potential_nosetest(item: Item) -> bool: |
26 |
| - # Extra check needed since we do not do nose style setup/teardown |
27 |
| - # on direct unittest style classes. |
28 |
| - return isinstance(item, python.Function) and not isinstance( |
29 |
| - item, unittest.TestCaseFunction |
30 |
| - ) |
| 10 | +def pytest_runtest_setup(item: Item) -> None: |
| 11 | + if not isinstance(item, Function): |
| 12 | + return |
| 13 | + # Don't do nose style setup/teardown on direct unittest style classes. |
| 14 | + if isinstance(item, TestCaseFunction): |
| 15 | + return |
| 16 | + |
| 17 | + # Capture the narrowed type of item for the teardown closure, |
| 18 | + # see https://github.com/python/mypy/issues/2608 |
| 19 | + func = item |
| 20 | + |
| 21 | + if not call_optional(func.obj, "setup"): |
| 22 | + # Call module level setup if there is no object level one. |
| 23 | + assert func.parent is not None |
| 24 | + call_optional(func.parent.obj, "setup") # type: ignore[attr-defined] |
| 25 | + |
| 26 | + def teardown_nose() -> None: |
| 27 | + if not call_optional(func.obj, "teardown"): |
| 28 | + assert func.parent is not None |
| 29 | + call_optional(func.parent.obj, "teardown") # type: ignore[attr-defined] |
| 30 | + |
| 31 | + # XXX This implies we only call teardown when setup worked. |
| 32 | + func.addfinalizer(teardown_nose) |
31 | 33 |
|
32 | 34 |
|
33 | 35 | def call_optional(obj: object, name: str) -> bool:
|
|
0 commit comments