From 8b511e5561edf9e1427fa523f6c82cc411fb5848 Mon Sep 17 00:00:00 2001 From: Emmanuel Ogbizi Date: Tue, 1 Jun 2021 19:35:45 -0400 Subject: [PATCH] fix: correctly use pytest invocation arguments (#507) --- src/syrupy/__init__.py | 13 +--- src/syrupy/report.py | 72 +++++++++---------- src/syrupy/session.py | 25 ++++--- .../test_snapshot_option_update.py | 6 +- 4 files changed, 53 insertions(+), 63 deletions(-) diff --git a/src/syrupy/__init__.py b/src/syrupy/__init__.py index f370353d..7edfdc4e 100644 --- a/src/syrupy/__init__.py +++ b/src/syrupy/__init__.py @@ -115,17 +115,10 @@ def pytest_sessionstart(session: Any) -> None: Initialize snapshot session before tests are collected and ran. https://docs.pytest.org/en/latest/reference.html#_pytest.hookspec.pytest_sessionstart """ - config = session.config - config._syrupy = SnapshotSession( - warn_unused_snapshots=config.option.warn_unused_snapshots, - update_snapshots=config.option.update_snapshots, - include_snapshot_details=config.option.include_snapshot_details, - base_dir=config.rootdir, - invocation_args=config.invocation_params.args, - ) + session.config._syrupy = SnapshotSession(pytest_session=session) global _syrupy - _syrupy = config._syrupy - config._syrupy.start() + _syrupy = session.config._syrupy + session.config._syrupy.start() def pytest_collection_modifyitems( diff --git a/src/syrupy/report.py b/src/syrupy/report.py index 7c4fdee9..94bf0639 100644 --- a/src/syrupy/report.py +++ b/src/syrupy/report.py @@ -11,9 +11,7 @@ FrozenSet, Iterator, List, - Optional, Set, - Tuple, ) import attr @@ -35,6 +33,8 @@ ) if TYPE_CHECKING: + import argparse + import pytest from .assertion import SnapshotAssertion @@ -51,9 +51,7 @@ class SnapshotReport: base_dir: str = attr.ib() collected_items: Set["pytest.Item"] = attr.ib() selected_items: Dict[str, bool] = attr.ib() - update_snapshots: bool = attr.ib() - warn_unused_snapshots: bool = attr.ib() - include_snapshot_details: bool = attr.ib() + options: "argparse.Namespace" = attr.ib() assertions: List["SnapshotAssertion"] = attr.ib() discovered: "SnapshotFossils" = attr.ib(factory=SnapshotFossils) created: "SnapshotFossils" = attr.ib(factory=SnapshotFossils) @@ -61,13 +59,24 @@ class SnapshotReport: matched: "SnapshotFossils" = attr.ib(factory=SnapshotFossils) updated: "SnapshotFossils" = attr.ib(factory=SnapshotFossils) used: "SnapshotFossils" = attr.ib(factory=SnapshotFossils) - _invocation_args: Tuple[str, ...] = attr.ib(factory=tuple) _provided_test_paths: Dict[str, List[str]] = attr.ib(factory=dict) _keyword_expressions: Set["Expression"] = attr.ib(factory=set) _collected_items_by_nodeid: Dict[str, "pytest.Item"] = attr.ib( factory=dict, init=False ) + @property + def update_snapshots(self) -> bool: + return bool(self.options.update_snapshots) + + @property + def warn_unused_snapshots(self) -> bool: + return bool(self.options.warn_unused_snapshots) + + @property + def include_snapshot_details(self) -> bool: + return bool(self.options.include_snapshot_details) + def __attrs_post_init__(self) -> None: self.__parse_invocation_args() self._collected_items_by_nodeid = { @@ -106,39 +115,24 @@ def __parse_invocation_args(self) -> None: would result in `"tests/test_file.py"` being stored as the location in a dictionary with `["TestClass", "test_method"]` being the test node path """ - arg_groups: List[Tuple[Optional[str], str]] = [] - path_as_package = False - maybe_opt_arg = None - for arg in self._invocation_args: - if arg.strip() == "--pyargs": - path_as_package = True - elif arg.startswith("-"): - if "=" in arg: - arg0, arg1 = arg.split("=") - arg_groups.append((arg0.strip(), arg1.strip())) - elif maybe_opt_arg is None: - maybe_opt_arg = arg - continue # do not reset maybe_opt_arg - else: - arg_groups.append((maybe_opt_arg, arg.strip())) - - maybe_opt_arg = None - - for maybe_opt_arg, arg_value in arg_groups: - if maybe_opt_arg == "-k": # or maybe_opt_arg == "-m": - self._keyword_expressions.add(Expression.compose(arg_value)) - elif maybe_opt_arg is None: - parts = arg_value.split(PYTEST_NODE_SEP) - package_or_filepath = parts[0].strip() - filepath = Path( - importlib.import_module(package_or_filepath).__file__ - if path_as_package - else package_or_filepath - ) - filepath_abs = str( - filepath if filepath.is_absolute() else filepath.absolute() - ) - self._provided_test_paths[filepath_abs] = parts[1:] + + if self.options.keyword: + self._keyword_expressions.add(Expression.compose(self.options.keyword)) + for file_or_dir in self.options.file_or_dir: + parts = file_or_dir.split(PYTEST_NODE_SEP) + package_or_filepath = parts[0].strip() + filepath = Path(package_or_filepath) + if self.options.pyargs: + try: + filepath = Path( + importlib.import_module(package_or_filepath).__file__ + ) + except Exception: + pass + filepath_abs = str( + filepath if filepath.is_absolute() else filepath.absolute() + ) + self._provided_test_paths[filepath_abs] = parts[1:] @property def num_created(self) -> int: diff --git a/src/syrupy/session.py b/src/syrupy/session.py index 591c620c..06ed0003 100644 --- a/src/syrupy/session.py +++ b/src/syrupy/session.py @@ -1,12 +1,12 @@ from pathlib import Path from typing import ( TYPE_CHECKING, + Any, Dict, Iterable, List, Optional, Set, - Tuple, ) import attr @@ -23,11 +23,9 @@ @attr.s class SnapshotSession: - base_dir: str = attr.ib() - update_snapshots: bool = attr.ib() - warn_unused_snapshots: bool = attr.ib() - include_snapshot_details: bool = attr.ib() - _invocation_args: Tuple[str, ...] = attr.ib(factory=tuple) + # pytest.Session + _pytest_session: Any = attr.ib() + # Snapshot report generated on finish report: Optional["SnapshotReport"] = attr.ib(default=None) # All the collected test items _collected_items: Set["pytest.Item"] = attr.ib(factory=set) @@ -36,6 +34,14 @@ class SnapshotSession: _assertions: List["SnapshotAssertion"] = attr.ib(factory=list) _extensions: Dict[str, "AbstractSyrupyExtension"] = attr.ib(factory=dict) + @property + def update_snapshots(self) -> bool: + return bool(self._pytest_session.config.option.update_snapshots) + + @property + def warn_unused_snapshots(self) -> bool: + return bool(self._pytest_session.config.option.warn_unused_snapshots) + def collect_items(self, items: List["pytest.Item"]) -> None: self._collected_items.update(self.filter_valid_items(items)) @@ -56,14 +62,11 @@ def ran_item(self, nodeid: str) -> None: def finish(self) -> int: exitstatus = 0 self.report = SnapshotReport( - base_dir=self.base_dir, + base_dir=self._pytest_session.config.rootdir, collected_items=self._collected_items, selected_items=self._selected_items, assertions=self._assertions, - update_snapshots=self.update_snapshots, - warn_unused_snapshots=self.warn_unused_snapshots, - include_snapshot_details=self.include_snapshot_details, - invocation_args=self._invocation_args, + options=self._pytest_session.config.option, ) if self.report.num_unused: if self.update_snapshots: diff --git a/tests/integration/test_snapshot_option_update.py b/tests/integration/test_snapshot_option_update.py index 2604ae93..2ce6fe71 100644 --- a/tests/integration/test_snapshot_option_update.py +++ b/tests/integration/test_snapshot_option_update.py @@ -315,7 +315,7 @@ def test_update_targets_only_selected_module_tests_nodes(run_testcases): snapfile_empty = Path("__snapshots__", "empty_snapfile.ambr") testdir.makefile(".ambr", **{str(snapfile_empty): ""}) testfile = Path(testdir.tmpdir, "test_used.py") - result = testdir.runpytest(f"{testfile}::test_used", "-v", "--snapshot-update") + result = testdir.runpytest("-v", f"{testfile}::test_used", "--snapshot-update") result.stdout.re_match_lines((r"3 snapshots passed\.")) assert "unused" not in result.stdout.str() assert "updated" not in result.stdout.str() @@ -357,7 +357,7 @@ def test_used(snapshot, actual): """ ) ) - result = testdir.runpytest("-v", "--snapshot-update", "test_used.py") + result = testdir.runpytest("-v", "test_used.py", "--snapshot-update") result.stdout.re_match_lines( ( r"3 snapshots passed\. 2 unused snapshots deleted\.", @@ -381,7 +381,7 @@ def test_used(snapshot): ) snapfile_empty = Path("__snapshots__", "empty_snapfile.ambr") testdir.makefile(".ambr", **{str(snapfile_empty): ""}) - result = testdir.runpytest("-v", "--snapshot-update", "test_used.py") + result = testdir.runpytest("-v", "test_used.py", "--snapshot-update") result.stdout.re_match_lines( ( r"5 unused snapshots deleted\.",