From 8309d88e63a59ec439f5dbc7f70f58ea6ffe669b Mon Sep 17 00:00:00 2001 From: Songpeng Liu Date: Fri, 27 Oct 2023 15:14:21 +1100 Subject: [PATCH] Add denote test --- AUTHORS | 1 + src/_pytest/assertion/rewrite.py | 1 + src/_pytest/cacheprovider.py | 0 src/_pytest/main.py | 9 ++++- src/_pytest/mark/structures.py | 67 ++++++++++++++++++++++++++++++++ src/_pytest/pytester.py | 1 + src/_pytest/python.py | 4 +- testing/11495.feature.rst | 4 ++ testing/test_denotation.py | 12 ++++++ 9 files changed, 95 insertions(+), 4 deletions(-) mode change 100755 => 100644 src/_pytest/cacheprovider.py create mode 100644 testing/11495.feature.rst create mode 100644 testing/test_denotation.py diff --git a/AUTHORS b/AUTHORS index be1e78638..0ed4f0b79 100644 --- a/AUTHORS +++ b/AUTHORS @@ -343,6 +343,7 @@ Simon Holesch Simon Kerr Skylar Downes Srinivas Reddy Thatiparthy +Songpeng Liu Stefaan Lippens Stefan Farmbauer Stefan Scherfke diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index fd2355297..cab54b16c 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -80,6 +80,7 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader) try: self.fnpats = config.getini("python_files") except ValueError: + print("debug in 75") self.fnpats = ["test_*.py", "*_test.py"] self.session: Optional[Session] = None self._rewritten_names: Dict[str, Path] = {} diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py old mode 100755 new mode 100644 diff --git a/src/_pytest/main.py b/src/_pytest/main.py index ea89a63fa..c948cb9fd 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -638,9 +638,8 @@ class Session(nodes.FSCollector): self._notfound: List[Tuple[str, Sequence[nodes.Collector]]] = [] self._initial_parts: List[Tuple[Path, List[str]]] = [] self.items: List[nodes.Item] = [] - + #import pdb; pdb.set_trace() hook = self.config.hook - items: Sequence[Union[nodes.Item, nodes.Collector]] = self.items try: initialpaths: List[Path] = [] @@ -682,6 +681,12 @@ class Session(nodes.FSCollector): hook.pytest_collection_finish(session=self) self.testscollected = len(items) + +# print("[lizhicheng]") +# print(len(items)) +# print(type(items)) +# print(items) +# # import pdb;pdb.set_trace() return items def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 55620f042..98032d750 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -616,3 +616,70 @@ class NodeKeywords(MutableMapping[str, Any]): def __repr__(self) -> str: return f"" + +@final +@dataclasses.dataclass(frozen=True) +class Test: + """A pytest test.""" + + #: Name of the test. + name: str + #: Positional arguments of the mark decorator. + args: Tuple[Any, ...] + #: Keyword arguments of the mark decorator. + kwargs: Mapping[str, Any] + + _param_ids_from: Optional["Test"] = dataclasses.field(default=None, repr=False) + #: Resolved/generated ids with parametrize Marks. + _param_ids_generated: Optional[Sequence[str]] = dataclasses.field( + default=None, repr=False + ) + + def __init__( + self, + name: str, + args: Tuple[Any, ...], + kwargs: Mapping[str, Any], + param_ids_from: Optional["Mark"] = None, + param_ids_generated: Optional[Sequence[str]] = None, + *, + _ispytest: bool = False, + ) -> None: + """:meta private:""" + check_ispytest(_ispytest) + # Weirdness to bypass frozen=True. + object.__setattr__(self, "name", name) + object.__setattr__(self, "args", args) + object.__setattr__(self, "kwargs", kwargs) + object.__setattr__(self, "_param_ids_from", param_ids_from) + object.__setattr__(self, "_param_ids_generated", param_ids_generated) + + def _has_param_ids(self) -> bool: + return "ids" in self.kwargs or len(self.args) >= 4 + + def combined_with(self, other: "Test") -> "Test": + """Return a new Test which is a combination of this + Test and another Test. + + Combines by appending args and merging kwargs. + + """ + assert self.name == other.name + + # Remember source of ids with parametrize Marks. + param_ids_from: Optional[Mark] = None + if self.name == "parametrize": + if other._has_param_ids(): + param_ids_from = other + elif self._has_param_ids(): + param_ids_from = self + + return Test( + self.name, + self.args + other.args, + dict(self.kwargs, **other.kwargs), + param_ids_from=param_ids_from, + _ispytest=True, + ) + + diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index cdfc2c04a..515845f7b 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1045,6 +1045,7 @@ class Pytester: return result def runitem(self, source: str) -> Any: + print(str) """Run the "test_func" Item. The calling test instance (class containing the test method) must diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 5f8be5d9b..a51e6f3a3 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -111,7 +111,7 @@ def pytest_addoption(parser: Parser) -> None: "python_files", type="args", # NOTE: default is also used in AssertionRewritingHook. - default=["test_*.py", "*_test.py"], + default=["test_*.py", "*_test.py", "myselftest_*.py"], help="Glob-style file patterns for Python test module discovery", ) parser.addini( @@ -123,7 +123,7 @@ def pytest_addoption(parser: Parser) -> None: parser.addini( "python_functions", type="args", - default=["test"], + default=["test", "my", "*"], help="Prefixes or glob names for Python test function and method discovery", ) parser.addini( diff --git a/testing/11495.feature.rst b/testing/11495.feature.rst new file mode 100644 index 000000000..ad282a406 --- /dev/null +++ b/testing/11495.feature.rst @@ -0,0 +1,4 @@ +Add denotation, users now can use annotation to denote a test: +@pytest.mark.test +def hello(): + assert 5 == 5 diff --git a/testing/test_denotation.py b/testing/test_denotation.py new file mode 100644 index 000000000..d805f6133 --- /dev/null +++ b/testing/test_denotation.py @@ -0,0 +1,12 @@ +# content of test_sample.py +import pytest + + +@pytest.mark.test +def mul(): + assert 24 == (4 * 6) + +def my_test(): + print("test_answer") + assert 5 == 5 +