Skip to content

Commit

Permalink
fix: unused snapshot not filtered out when tests have similar names, c…
Browse files Browse the repository at this point in the history
…lose #529 (#531)
  • Loading branch information
Noah committed Aug 18, 2021
1 parent c8ed886 commit d0c8ca8
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 12 deletions.
47 changes: 35 additions & 12 deletions src/syrupy/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,14 @@ def unused(self) -> "SnapshotFossils":
unused_snapshots = {
snapshot
for snapshot in unused_snapshot_fossil
if self._selected_items_match_name(snapshot.name)
or self._provided_nodes_match_name(snapshot.name, provided_nodes)
if self._selected_items_match_name(
snapshot_location=snapshot_location, snapshot_name=snapshot.name
)
and self._provided_nodes_match_name(
snapshot_location=snapshot_location,
snapshot_name=snapshot.name,
provided_nodes=provided_nodes,
)
}
mark_for_removal = False

Expand Down Expand Up @@ -343,12 +349,22 @@ def _get_matching_path_nodes(self, snapshot_location: str) -> List[List[str]]:
]

def _provided_nodes_match_name(
self, snapshot_name: str, provided_nodes: List[List[str]]
self,
snapshot_location: str,
snapshot_name: str,
provided_nodes: List[List[str]],
) -> bool:
"""
Check that a snapshot name matches the node paths provided
Check that a snapshot name matches the node paths provided.
If no nodes are filtered, provided_nodes is empty, which means
all nodes should be matched.
"""
return any(snapshot_name in ".".join(node_path) for node_path in provided_nodes)
if not provided_nodes:
return True
for node_path in provided_nodes:
if snapshot_name in ".".join(node_path):
return True
return False

def _provided_keywords_match_name(self, snapshot_name: str) -> bool:
"""
Expand All @@ -361,23 +377,30 @@ def _provided_keywords_match_name(self, snapshot_name: str) -> bool:
for expr in self._keyword_expressions
)

def _ran_items_match_name(self, snapshot_name: str) -> bool:
def _ran_items_match_name(self, snapshot_location: str, snapshot_name: str) -> bool:
"""
Check that a snapshot name would match a test node using the Pytest location
"""
return any(
PyTestLocation(item).matches_snapshot_name(snapshot_name)
for item in self.ran_items
)
for item in self.ran_items:
location = PyTestLocation(item)
if location.matches_snapshot_location(
snapshot_location
) and location.matches_snapshot_name(snapshot_name):
return True
return False

def _selected_items_match_name(self, snapshot_name: str) -> bool:
def _selected_items_match_name(
self, snapshot_location: str, snapshot_name: str
) -> bool:
"""
Check that a snapshot name should be treated as selected by the current session
This being true means that if the snapshot was not used then it will be deleted
"""
if self._keyword_expressions:
return self._provided_keywords_match_name(snapshot_name)
return self._ran_items_match_name(snapshot_name)
return self._ran_items_match_name(
snapshot_location=snapshot_location, snapshot_name=snapshot_name
)

def _ran_items_match_location(self, snapshot_location: str) -> bool:
"""
Expand Down
2 changes: 2 additions & 0 deletions tasks/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def test(
test_pattern=None,
update_snapshots=False,
verbose=False,
debug=False,
):
"""
Run entire test suite
Expand All @@ -27,6 +28,7 @@ def test(
"-s -vv": verbose,
f"-k {test_pattern}": test_pattern,
"--snapshot-update": update_snapshots,
"--pdb": debug,
}
coverage_module = "coverage run -m " if coverage else ""
test_flags = " ".join(flag for flag, enabled in flags.items() if enabled)
Expand Down
76 changes: 76 additions & 0 deletions tests/integration/test_snapshot_similar_names_default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import pytest


@pytest.fixture
def testcases():
return {
"a": (
"""
def test_a(snapshot):
assert snapshot == 'a'
"""
),
"b": (
"""
def test_b(snapshot):
assert snapshot == 'b'
"""
),
}


@pytest.fixture
def run_testcases(testdir, testcases):
pyfile_content = "\n\n".join(testcases.values())
testdir.makepyfile(test_1=pyfile_content, test_2=pyfile_content)
result = testdir.runpytest("-v", "--snapshot-update")
result.stdout.re_match_lines((r"4 snapshots generated\."))
return testdir, testcases


def test_run_all(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest("-v")
result.stdout.re_match_lines("4 snapshots passed")
assert result.ret == 0


def test_run_single_file(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest("-v", "test_1.py")
result.stdout.re_match_lines("2 snapshots passed")
assert result.ret == 0


def test_run_single_test_case_in_file(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest("-v", "test_2.py::test_a")
result.stdout.re_match_lines("1 snapshot passed")
assert result.ret == 0


def test_run_all_but_one(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v", "--snapshot-details", "test_1.py", "test_2.py::test_a"
)
result.stdout.re_match_lines("3 snapshots passed")
assert result.ret == 0


def test_run_both_files_by_node(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v", "--snapshot-details", "test_1.py::test_a", "test_2.py::test_a"
)
result.stdout.re_match_lines("2 snapshots passed")
assert result.ret == 0


def test_run_both_files_by_node_2(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v", "--snapshot-details", "test_1.py::test_b", "test_2.py::test_a"
)
result.stdout.re_match_lines("2 snapshots passed")
assert result.ret == 0
110 changes: 110 additions & 0 deletions tests/integration/test_snapshot_similar_names_file_extension.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import pytest


@pytest.fixture
def testcases():
return {
"a": (
"""
def test_a(snapshot):
assert snapshot == b"a"
"""
),
"b": (
"""
def test_b(snapshot):
assert snapshot == b"b"
"""
),
}


@pytest.fixture
def run_testcases(testdir, testcases):
pyfile_content = "\n\n".join(testcases.values())
testdir.makepyfile(test_1=pyfile_content, test_2=pyfile_content)
result = testdir.runpytest(
"-v",
"--snapshot-update",
"--snapshot-default-extension",
"syrupy.extensions.single_file.SingleFileSnapshotExtension",
)
result.stdout.re_match_lines((r"4 snapshots generated\."))
return testdir, testcases


def test_run_all(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v",
"--snapshot-default-extension",
"syrupy.extensions.single_file.SingleFileSnapshotExtension",
)
result.stdout.re_match_lines("4 snapshots passed")
assert result.ret == 0


def test_run_single_file(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v",
"--snapshot-default-extension",
"syrupy.extensions.single_file.SingleFileSnapshotExtension",
"test_1.py",
)
result.stdout.re_match_lines("2 snapshots passed")
assert result.ret == 0


def test_run_single_test_case_in_file(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v",
"--snapshot-default-extension",
"syrupy.extensions.single_file.SingleFileSnapshotExtension",
"test_2.py::test_a",
)
result.stdout.re_match_lines("1 snapshot passed")
assert result.ret == 0


def test_run_all_but_one(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v",
"--snapshot-details",
"--snapshot-default-extension",
"syrupy.extensions.single_file.SingleFileSnapshotExtension",
"test_1.py",
"test_2.py::test_a",
)
result.stdout.re_match_lines("3 snapshots passed")
assert result.ret == 0


def test_run_both_files_by_node(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v",
"--snapshot-details",
"--snapshot-default-extension",
"syrupy.extensions.single_file.SingleFileSnapshotExtension",
"test_1.py::test_a",
"test_2.py::test_a",
)
result.stdout.re_match_lines("2 snapshots passed")
assert result.ret == 0


def test_run_both_files_by_node_2(run_testcases):
testdir, testcases = run_testcases
result = testdir.runpytest(
"-v",
"--snapshot-details",
"--snapshot-default-extension",
"syrupy.extensions.single_file.SingleFileSnapshotExtension",
"test_1.py::test_b",
"test_2.py::test_a",
)
result.stdout.re_match_lines("2 snapshots passed")
assert result.ret == 0

0 comments on commit d0c8ca8

Please sign in to comment.