Merge branch 'pytest-dev:main' into remove-eq-format
This commit is contained in:
commit
7cf2b51d8e
|
@ -33,10 +33,10 @@ if TYPE_CHECKING:
|
|||
from _pytest.nodes import Collector
|
||||
from _pytest.nodes import Item
|
||||
from _pytest.outcomes import Exit
|
||||
from _pytest.python import Class
|
||||
from _pytest.python import Function
|
||||
from _pytest.python import Metafunc
|
||||
from _pytest.python import Module
|
||||
from _pytest.python import PyCollector
|
||||
from _pytest.reports import CollectReport
|
||||
from _pytest.reports import TestReport
|
||||
from _pytest.runner import CallInfo
|
||||
|
@ -359,7 +359,7 @@ def pytest_pycollect_makemodule(
|
|||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_pycollect_makeitem(
|
||||
collector: "PyCollector", name: str, obj: object
|
||||
collector: Union["Module", "Class"], name: str, obj: object
|
||||
) -> Union[None, "Item", "Collector", List[Union["Item", "Collector"]]]:
|
||||
"""Return a custom item/collector for a Python object in a module, or None.
|
||||
|
||||
|
|
|
@ -224,11 +224,15 @@ def pytest_pycollect_makemodule(module_path: Path, parent) -> "Module":
|
|||
|
||||
|
||||
@hookimpl(trylast=True)
|
||||
def pytest_pycollect_makeitem(collector: "PyCollector", name: str, obj: object):
|
||||
def pytest_pycollect_makeitem(
|
||||
collector: Union["Module", "Class"], name: str, obj: object
|
||||
) -> Union[None, nodes.Item, nodes.Collector, List[Union[nodes.Item, nodes.Collector]]]:
|
||||
assert isinstance(collector, (Class, Module)), type(collector)
|
||||
# Nothing was collected elsewhere, let's do it here.
|
||||
if safe_isclass(obj):
|
||||
if collector.istestclass(obj, name):
|
||||
return Class.from_parent(collector, name=name, obj=obj)
|
||||
klass: Class = Class.from_parent(collector, name=name, obj=obj)
|
||||
return klass
|
||||
elif collector.istestfunction(obj, name):
|
||||
# mock seems to store unbound methods (issue473), normalize it.
|
||||
obj = getattr(obj, "__func__", obj)
|
||||
|
@ -247,15 +251,16 @@ def pytest_pycollect_makeitem(collector: "PyCollector", name: str, obj: object):
|
|||
)
|
||||
elif getattr(obj, "__test__", True):
|
||||
if is_generator(obj):
|
||||
res = Function.from_parent(collector, name=name)
|
||||
res: Function = Function.from_parent(collector, name=name)
|
||||
reason = "yield tests were removed in pytest 4.0 - {name} will be ignored".format(
|
||||
name=name
|
||||
)
|
||||
res.add_marker(MARK_GEN.xfail(run=False, reason=reason))
|
||||
res.warn(PytestCollectionWarning(reason))
|
||||
return res
|
||||
else:
|
||||
res = list(collector._genfunctions(name, obj))
|
||||
return res
|
||||
return list(collector._genfunctions(name, obj))
|
||||
return None
|
||||
|
||||
|
||||
class PyobjMixin(nodes.Node):
|
||||
|
|
|
@ -27,7 +27,7 @@ from _pytest.outcomes import skip
|
|||
from _pytest.outcomes import xfail
|
||||
from _pytest.python import Class
|
||||
from _pytest.python import Function
|
||||
from _pytest.python import PyCollector
|
||||
from _pytest.python import Module
|
||||
from _pytest.runner import CallInfo
|
||||
from _pytest.scope import Scope
|
||||
|
||||
|
@ -42,7 +42,7 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
def pytest_pycollect_makeitem(
|
||||
collector: PyCollector, name: str, obj: object
|
||||
collector: Union[Module, Class], name: str, obj: object
|
||||
) -> Optional["UnitTestCase"]:
|
||||
# Has unittest been imported and is obj a subclass of its TestCase?
|
||||
try:
|
||||
|
|
|
@ -335,6 +335,54 @@ def test_sessionfinish_with_start(pytester: Pytester) -> None:
|
|||
assert res.ret == ExitCode.NO_TESTS_COLLECTED
|
||||
|
||||
|
||||
def test_collection_args_do_not_duplicate_modules(pytester: Pytester) -> None:
|
||||
"""Test that when multiple collection args are specified on the command line
|
||||
for the same module, only a single Module collector is created.
|
||||
|
||||
Regression test for #723, #3358.
|
||||
"""
|
||||
pytester.makepyfile(
|
||||
**{
|
||||
"d/test_it": """
|
||||
def test_1(): pass
|
||||
def test_2(): pass
|
||||
"""
|
||||
}
|
||||
)
|
||||
|
||||
result = pytester.runpytest(
|
||||
"--collect-only",
|
||||
"d/test_it.py::test_1",
|
||||
"d/test_it.py::test_2",
|
||||
)
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"<Module d/test_it.py>",
|
||||
" <Function test_1>",
|
||||
" <Function test_2>",
|
||||
],
|
||||
consecutive=True,
|
||||
)
|
||||
|
||||
# Different, but related case.
|
||||
result = pytester.runpytest(
|
||||
"--collect-only",
|
||||
"--keep-duplicates",
|
||||
"d",
|
||||
"d",
|
||||
)
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"<Module d/test_it.py>",
|
||||
" <Function test_1>",
|
||||
" <Function test_2>",
|
||||
" <Function test_1>",
|
||||
" <Function test_2>",
|
||||
],
|
||||
consecutive=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", ["root", "{relative}/root", "{environment}/root"])
|
||||
def test_rootdir_option_arg(
|
||||
pytester: Pytester, monkeypatch: MonkeyPatch, path: str
|
||||
|
|
Loading…
Reference in New Issue