Skip to content

Commit

Permalink
Improve iterparentnodeids to consume / parts until the first :: (
Browse files Browse the repository at this point in the history
…#8577)

* Fix issue where TestCase.setUpClass is not called for test methods with a / in its name by checking if there is ::  before the selected / or any :: after. Also added a test case for this.

* removed print statement that was added

* Change iterparentnodeids to consume / parts until the first ::. Then consider ::. Tests were changed to reflect this.

* Update changelog/8509.improvement.rst

Co-authored-by: Ran Benita <ran@unusedvar.com>
  • Loading branch information
parthdpa and bluetech committed Apr 29, 2021
1 parent 2049ae2 commit 992c403
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 14 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ Omar Kohl
Omer Hadari
Ondřej Súkup
Oscar Benjamin
Parth Patel
Patrick Hayes
Pauli Virtanen
Pavel Karateev
Expand Down
5 changes: 5 additions & 0 deletions changelog/8509.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Fixed issue where `TestCase.setUpClass` is not called when a test has `/` in its name since pytest 6.2.0.

This refers to the path part in pytest node IDs, e.g. `TestClass::test_it` in the node ID `tests/test_file.py::TestClass::test_it`.

Now, instead of assuming that the test name does not contain ``/``, it is assumed that test path does not contain ``::``. We plan to hopefully make both of these work in the future.
34 changes: 22 additions & 12 deletions src/_pytest/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,33 @@ def iterparentnodeids(nodeid: str) -> Iterator[str]:
"testing/code/test_excinfo.py::TestFormattedExcinfo"
"testing/code/test_excinfo.py::TestFormattedExcinfo::test_repr_source"
Note that :: parts are only considered at the last / component.
Note that / components are only considered until the first ::.
"""
pos = 0
sep = SEP
first_colons: Optional[int] = nodeid.find("::")
if first_colons == -1:
first_colons = None
# The root Session node - always present.
yield ""
# Eagerly consume SEP parts until first colons.
while True:
at = nodeid.find(sep, pos)
if at == -1 and sep == SEP:
sep = "::"
elif at == -1:
if nodeid:
yield nodeid
at = nodeid.find(SEP, pos, first_colons)
if at == -1:
break
else:
if at:
yield nodeid[:at]
pos = at + len(sep)
if at > 0:
yield nodeid[:at]
pos = at + len(SEP)
# Eagerly consume :: parts.
while True:
at = nodeid.find("::", pos)
if at == -1:
break
if at > 0:
yield nodeid[:at]
pos = at + len("::")
# The node ID itself.
if nodeid:
yield nodeid


def _imply_path(
Expand Down
6 changes: 4 additions & 2 deletions testing/test_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
("a/b/c", ["", "a", "a/b", "a/b/c"]),
("a/bbb/c::D", ["", "a", "a/bbb", "a/bbb/c", "a/bbb/c::D"]),
("a/b/c::D::eee", ["", "a", "a/b", "a/b/c", "a/b/c::D", "a/b/c::D::eee"]),
# :: considered only at the last component.
("::xx", ["", "::xx"]),
("a/b/c::D/d::e", ["", "a", "a/b", "a/b/c::D", "a/b/c::D/d", "a/b/c::D/d::e"]),
# / only considered until first ::
("a/b/c::D/d::e", ["", "a", "a/b", "a/b/c", "a/b/c::D/d", "a/b/c::D/d::e"]),
# : alone is not a separator.
("a/b::D:e:f::g", ["", "a", "a/b", "a/b::D:e:f", "a/b::D:e:f::g"]),
# / not considered if a part of a test name
("a/b::c/d::e[/test]", ["", "a", "a/b", "a/b::c/d", "a/b::c/d::e[/test]"]),
),
)
def test_iterparentnodeids(nodeid: str, expected: List[str]) -> None:
Expand Down

0 comments on commit 992c403

Please sign in to comment.