def test_exception_repr_extraction_error_on_recursion(): """ Ensure we can properly detect a recursion error even if some locals raise error on comparision (#2459). """ class numpy_like(object): def __eq__(self, other): if type(other) is numpy_like: raise ValueError('The truth value of an array ' 'with more than one element is ambiguous.') def a(x): return b(numpy_like()) def b(x): return a(numpy_like()) try: a(numpy_like()) except: # noqa from _pytest._code.code import ExceptionInfo from _pytest.pytester import LineMatcher exc_info = ExceptionInfo() matcher = LineMatcher(str(exc_info.getrepr()).splitlines()) matcher.fnmatch_lines([ '!!! Recursion error detected, but an error occurred locating the origin of recursion.', '*The following exception happened*', '*ValueError: The truth value of an array*', ])
def test_exception_repr_extraction_error_on_recursion(): """ Ensure we can properly detect a recursion error even if some locals raise error on comparison (#2459). """ from _pytest.pytester import LineMatcher class numpy_like(object): def __eq__(self, other): if type(other) is numpy_like: raise ValueError( "The truth value of an array " "with more than one element is ambiguous." ) def a(x): return b(numpy_like()) def b(x): return a(numpy_like()) with pytest.raises(RuntimeError) as excinfo: a(numpy_like()) matcher = LineMatcher(str(excinfo.getrepr()).splitlines()) matcher.fnmatch_lines( [ "!!! Recursion error detected, but an error occurred locating the origin of recursion.", "*The following exception happened*", "*ValueError: The truth value of an array*", ] )
def test_all(self, testdir, pastebinlist): from _pytest.pytester import LineMatcher testpath = testdir.makepyfile( """ import pytest def test_pass(): pass def test_fail(): assert 0 def test_skip(): pytest.skip("") """ ) reprec = testdir.inline_run(testpath, "--pastebin=all", "-v") assert reprec.countoutcomes() == [1, 1, 1] assert len(pastebinlist) == 1 contents = pastebinlist[0].decode("utf-8") matcher = LineMatcher(contents.splitlines()) matcher.fnmatch_lines( [ "*test_pass PASSED*", "*test_fail FAILED*", "*test_skip SKIPPED*", "*== 1 failed, 1 passed, 1 skipped in *", ] )
def test_linematcher_with_nonlist(): """Test LineMatcher with regard to passing in a set (accidentally).""" lm = LineMatcher([]) with pytest.raises(AssertionError): lm.fnmatch_lines(set()) with pytest.raises(AssertionError): lm.fnmatch_lines({}) lm.fnmatch_lines([]) lm.fnmatch_lines(()) assert lm._getlines({}) == {} assert lm._getlines(set()) == set()
def test_exc_chain_repr_without_traceback(self, importasmod, reason, description): """ Handle representation of exception chains where one of the exceptions doesn't have a real traceback, such as those raised in a subprocess submitted by the multiprocessing module (#1984). """ from _pytest.pytester import LineMatcher exc_handling_code = " from e" if reason == "cause" else "" mod = importasmod( """ def f(): try: g() except Exception as e: raise RuntimeError('runtime problem'){exc_handling_code} def g(): raise ValueError('invalid value') """.format( exc_handling_code=exc_handling_code ) ) with pytest.raises(RuntimeError) as excinfo: mod.f() # emulate the issue described in #1984 attr = "__%s__" % reason getattr(excinfo.value, attr).__traceback__ = None r = excinfo.getrepr() tw = py.io.TerminalWriter(stringio=True) tw.hasmarkup = False r.toterminal(tw) matcher = LineMatcher(tw.stringio.getvalue().splitlines()) matcher.fnmatch_lines( [ "ValueError: invalid value", description, "* except Exception as e:", "> * raise RuntimeError('runtime problem')" + exc_handling_code, "E *RuntimeError: runtime problem", ] )
def test_linematcher_no_matching_after_match() -> None: lm = LineMatcher(["1", "2", "3"]) lm.fnmatch_lines(["1", "3"]) with pytest.raises(Failed) as e: lm.no_fnmatch_line("*") assert str(e.value).splitlines() == ["fnmatch: '*'", " with: '1'"]
def _getmatcher(): lines = out.getvalue().split("\n") return LineMatcher(lines)
def test_linematcher_with_nonlist() -> None: """Test LineMatcher with regard to passing in a set (accidentally).""" from _pytest._code.source import Source lm = LineMatcher([]) with pytest.raises(TypeError, match="invalid type for lines2: set"): lm.fnmatch_lines(set()) # type: ignore[arg-type] # noqa: F821 with pytest.raises(TypeError, match="invalid type for lines2: dict"): lm.fnmatch_lines({}) # type: ignore[arg-type] # noqa: F821 with pytest.raises(TypeError, match="invalid type for lines2: set"): lm.re_match_lines(set()) # type: ignore[arg-type] # noqa: F821 with pytest.raises(TypeError, match="invalid type for lines2: dict"): lm.re_match_lines({}) # type: ignore[arg-type] # noqa: F821 with pytest.raises(TypeError, match="invalid type for lines2: Source"): lm.fnmatch_lines(Source()) # type: ignore[arg-type] # noqa: F821 lm.fnmatch_lines([]) lm.fnmatch_lines(()) lm.fnmatch_lines("") assert lm._getlines({}) == {} # type: ignore[arg-type,comparison-overlap] # noqa: F821 assert lm._getlines(set()) == set() # type: ignore[arg-type,comparison-overlap] # noqa: F821 assert lm._getlines(Source()) == [] assert lm._getlines(Source("pass\npass")) == ["pass", "pass"]
def test_multiple_processes_logging_log_file(logging_master, matches): # And on the log file, we also have matches? matcher = LineMatcher(logging_master.log_file.read_text().splitlines()) matcher.fnmatch_lines_random(matches)
def test_multiple_processes_logging_stderr(logging_master, matches): # Are we seeing the main pid in the STDERR getting logged? # And there must be more than the main process in the STDERR logs matcher = LineMatcher(logging_master.ret.stderr.splitlines()) matcher.fnmatch_lines_random(matches)
def test_linematcher_string_api() -> None: lm = LineMatcher(["foo", "bar"]) assert str(lm) == "foo\nbar"
def __init__(self, dir, filepath): lines = dir.join(filepath).read().splitlines() LineMatcher.__init__(self, lines)
def test_no_matching_after_match(): lm = LineMatcher(["1", "2", "3"]) lm.fnmatch_lines(["1", "3"]) with pytest.raises(pytest.fail.Exception) as e: lm.no_fnmatch_line("*") assert str(e.value).splitlines() == ["fnmatch: '*'", " with: '1'"]