Skip to content

Commit

Permalink
Introduce no_fnmatch_line/no_re_match_line in pytester
Browse files Browse the repository at this point in the history
The current idiom is to use:

  assert re.match(...) in result.stdout.str()

But this does not really give good results when it fails.

Those new functions produce similar output to ther other match lines functions.
  • Loading branch information
nicoddemus committed Oct 5, 2019
1 parent c1361b4 commit 2df6969
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 4 deletions.
43 changes: 39 additions & 4 deletions src/_pytest/pytester.py
Expand Up @@ -1319,8 +1319,7 @@ def fnmatch_lines(self, lines2):
The argument is a list of lines which have to match and can use glob
wildcards. If they do not match a pytest.fail() is called. The
matches and non-matches are also printed on stdout.
matches and non-matches are also shown as part of the error message.
"""
__tracebackhide__ = True
self._match_lines(lines2, fnmatch, "fnmatch")
Expand All @@ -1331,8 +1330,7 @@ def re_match_lines(self, lines2):
The argument is a list of lines which have to match using ``re.match``.
If they do not match a pytest.fail() is called.
The matches and non-matches are also printed on stdout.
The matches and non-matches are also shown as part of the error message.
"""
__tracebackhide__ = True
self._match_lines(lines2, lambda name, pat: re.match(pat, name), "re.match")
Expand Down Expand Up @@ -1375,3 +1373,40 @@ def _match_lines(self, lines2, match_func, match_nickname):
else:
self._log("remains unmatched: {!r}".format(line))
pytest.fail(self._log_text)

def no_fnmatch_line(self, pat):
"""Ensure captured lines do not match the given pattern, using ``fnmatch.fnmatch``.
:param str pat: the pattern to match lines.
"""
__tracebackhide__ = True
self._no_match_line(pat, fnmatch, "fnmatch")

def no_re_match_line(self, pat):
"""Ensure captured lines do not match the given pattern, using ``re.match``.
:param str pat: the regular expression to match lines.
"""
__tracebackhide__ = True
self._no_match_line(pat, lambda name, pat: re.match(pat, name), "re.match")

def _no_match_line(self, pat, match_func, match_nickname):
"""Ensure captured lines does not have a the given pattern, using ``fnmatch.fnmatch``
:param str pat: the pattern to match lines
"""
__tracebackhide__ = True
nomatch_printed = False
try:
for line in self.lines:
if match_func(line, pat):
self._log("%s:" % match_nickname, repr(pat))
self._log(" with:", repr(line))
pytest.fail(self._log_text)
else:
if not nomatch_printed:
self._log("nomatch:", repr(pat))
nomatch_printed = True
self._log(" and:", repr(line))
finally:
self._log_output = []
46 changes: 46 additions & 0 deletions testing/test_pytester.py
Expand Up @@ -457,6 +457,52 @@ def test_linematcher_with_nonlist():
assert lm._getlines(set()) == set()


@pytest.mark.parametrize("function", ["no_fnmatch_line", "no_re_match_line"])
def test_no_matching(function):
""""""
if function == "no_fnmatch_line":
match_func_name = "fnmatch"
good_pattern = "*.py OK*"
bad_pattern = "*X.py OK*"
else:
assert function == "no_re_match_line"
match_func_name = "re.match"
good_pattern = r".*py OK"
bad_pattern = r".*Xpy OK"

lm = LineMatcher(
[
"cachedir: .pytest_cache",
"collecting ... collected 1 item",
"",
"show_fixtures_per_test.py OK",
"=== elapsed 1s ===",
]
)

def check_failure_lines(lines):
expected = [
"nomatch: '{}'".format(good_pattern),
" and: 'cachedir: .pytest_cache'",
" and: 'collecting ... collected 1 item'",
" and: ''",
"{}: '{}'".format(match_func_name, good_pattern),
" with: 'show_fixtures_per_test.py OK'",
]
assert lines == expected

# check the function twice to ensure we don't accumulate the internal buffer
for i in range(2):
with pytest.raises(pytest.fail.Exception) as e:
func = getattr(lm, function)
func(good_pattern)
obtained = str(e.value).splitlines()
check_failure_lines(obtained)

func = getattr(lm, function)
func(bad_pattern) # bad pattern does not match any line: passes


def test_pytester_addopts(request, monkeypatch):
monkeypatch.setenv("PYTEST_ADDOPTS", "--orig-unused")

Expand Down

0 comments on commit 2df6969

Please sign in to comment.