Skip to content

Commit

Permalink
Use pytest data to extract the parametrised decoration
Browse files Browse the repository at this point in the history
Rather than try and parse out the parametrized portion of the nodeid (delimited by square brackets but possibly containing square brackets), use native [pytest item attributes](https://docs.pytest.org/en/6.2.x/reference.html#function) to separate out the decoration.

Better solution for microsoft#17357, fixing microsoft#17676.
  • Loading branch information
mjpieters authored Oct 30, 2021
1 parent 9bf27f2 commit c7c9607
Showing 1 changed file with 15 additions and 39 deletions.
54 changes: 15 additions & 39 deletions pythonFiles/testing_tools/adapter/pytest/_pytest_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,21 @@ def parse_item(
# Skip plugin generated tests
if kind is None:
return None, None
(nodeid, parents, fileid, testfunc, parameterized) = _parse_node_id(
item.nodeid, kind
)

if kind == "function" and item.originalname != item.name:
# split out parametrized decorations `node[params]`) before parsing
# and manually attach parametrized portion back in when done.
parameterized = item.name[len(item.originalname) :]
(parentid, parents, fileid, testfunc, _) = _parse_node_id(
item.nodeid[: -len(parameterized)], kind
)
nodeid = f"{parentid}{parameterized}"
parents = [(parentid, item.originalname, kind), *parents]
else:
(nodeid, parents, fileid, testfunc, parameterized) = _parse_node_id(
item.nodeid, kind
)

# Note: testfunc does not necessarily match item.function.__name__.
# This can result from importing a test function from another module.

Expand Down Expand Up @@ -434,32 +446,6 @@ def _parse_node_id(
)


def _find_left_bracket(nodeid):
"""Return tuple of part before final bracket open, separator [, and the remainder.
Notes:
Testcase names in case of parametrized tests are wrapped in [<test-case-name>].
Examples:
dirname[sometext]/dirname/testfile.py::testset::testname[testcase]
=> ('dirname[sometext]/dirname/testfile.py::testset::testname', '[', 'testcase]')
dirname/dirname/testfile.py::testset::testname[testcase]
=> ('dirname/dirname/testfile.py::testset::testname', '[', 'testcase]')
dirname/dirname/testfile.py::testset::testname[testcase[x]]
=> ('dirname/dirname/testfile.py::testset::testname', '[', 'testcase[x]]')
"""
if not nodeid.endswith("]"):
return nodeid, "", ""
bracketcount = 0
for index, char in enumerate(nodeid[::-1]):
if char == "]":
bracketcount += 1
elif char == "[":
bracketcount -= 1
if bracketcount == 0:
n = len(nodeid) - 1 - index
return nodeid[:n], nodeid[n], nodeid[n + 1 :]
return nodeid, "", ""


def _iter_nodes(
testid,
kind,
Expand All @@ -473,16 +459,6 @@ def _iter_nodes(
if len(nodeid) > len(testid):
testid = "." + _pathsep + testid

if kind == "function" and nodeid.endswith("]"):
funcid, sep, parameterized = _find_left_bracket(nodeid)
if not sep:
raise should_never_reach_here(
nodeid,
# ...
)
yield (nodeid, sep + parameterized, "subtest")
nodeid = funcid

parentid, _, name = nodeid.rpartition("::")
if not parentid:
if kind is None:
Expand Down

0 comments on commit c7c9607

Please sign in to comment.