def test_debug_trace_pid(self): out_lines = self.f1_debug_output(["trace", "pid"]) # Now our lines are always prefixed with the process id. pid_prefix = r"^%5d\.[0-9a-f]{4}: " % os.getpid() pid_lines = re_lines(out_lines, pid_prefix) self.assertEqual(pid_lines, out_lines) # We still have some tracing, and some not tracing. self.assertTrue(re_lines(out_lines, pid_prefix + "Tracing ")) self.assertTrue(re_lines(out_lines, pid_prefix + "Not tracing "))
def test_debug_trace_pid(self): out_lines = self.f1_debug_output(["trace", "pid"]) # Now our lines are always prefixed with the process id. pid_prefix = r"^%5d\.[0-9a-f]{4}: " % os.getpid() pid_lines = re_lines(out_lines, pid_prefix) assert pid_lines == out_lines # We still have some tracing, and some not tracing. assert re_lines(out_lines, pid_prefix + "Tracing ") assert re_lines(out_lines, pid_prefix + "Not tracing ")
def test_debug_trace(self): out_lines = self.f1_debug_output(["trace"]) # We should have a line like "Tracing 'f1.py'", perhaps with an # absolute path. f1 = re_lines(out_lines, r"Tracing '.*f1.py'") assert f1 # We should have lines like "Not tracing 'collector.py'..." coverage_lines = re_lines(out_lines, r"^Not tracing .*: is part of coverage.py$") assert coverage_lines
def test_debug_callers(self): out_lines = self.f1_debug_output(["pid", "dataop", "dataio", "callers"]) print(out_lines) # For every real message, there should be a stack # trace with a line like "f1_debug_output : /Users/ned/coverage/tests/test_debug.py @71" real_messages = re_lines(out_lines, r" @\d+", match=False).splitlines() frame_pattern = r"\s+f1_debug_output : .*tests[/\\]test_debug.py @\d+$" frames = re_lines(out_lines, frame_pattern).splitlines() self.assertEqual(len(real_messages), len(frames)) # The last message should be "Writing data", and the last frame should # be write_file in data.py. self.assertRegex(real_messages[-1], r"^\s*\d+\.\w{4}: Writing data") last_line = out_lines.splitlines()[-1] self.assertRegex(last_line, r"\s+write_file : .*coverage[/\\]data.py @\d+$")
def package_and_class_tags(self, cov): """Run an XML report on `cov`, and get the package and class tags.""" self.captured_stdout.truncate(0) cov.xml_report(outfile="-") packages_and_classes = re_lines(self.stdout(), r"<package |<class ") scrubs = r' branch-rate="0"| complexity="0"| line-rate="[\d.]+"' return clean(packages_and_classes, scrubs)
def test_code_throws(self): self.make_file( "throw.py", """\ def f1(): raise Exception("hey!") def f2(): f1() f2() """) # The important thing is for "coverage run" and "python" to report the # same traceback. status, out = self.run_command_status("coverage run throw.py") out2 = self.run_command("python throw.py") if env.PYPY: # Pypy has an extra frame in the traceback for some reason out2 = re_lines(out2, "toplevel", match=False) self.assertMultiLineEqual(out, out2) # But also make sure that the output is what we expect. self.assertIn('File "throw.py", line 5, in f2', out) self.assertIn('raise Exception("hey!")', out) self.assertNotIn('coverage', out) self.assertEqual(status, 1)
def assert_tryexecfile_output(self, out1, out2): """Assert that the output we got is a successful run of try_execfile.py. `out1` and `out2` must be the same, modulo a few slight known platform differences. """ # First, is this even credible try_execfile.py output? self.assertIn('"DATA": "xyzzy"', out1) if env.JYTHON: # pragma: only jython # Argv0 is different for Jython, remove that from the comparison. out1 = re_lines(out1, r'\s+"argv0":', match=False) out2 = re_lines(out2, r'\s+"argv0":', match=False) self.assertMultiLineEqual(out1, out2)
def test_venv_isnt_measured(self, coverage_command): out = run_in_venv(coverage_command + " run myproduct.py") assert out == self.expected_stdout debug_out = self.get_trace_output() assert re_lines( r"^Not tracing .*\bexecfile.py': is part of coverage.py", debug_out) assert re_lines(r"^Tracing .*\bmyproduct.py", debug_out) assert re_lines(r"^Not tracing .*\bcolorsys.py': is in the stdlib", debug_out) out = run_in_venv(coverage_command + " report") assert "myproduct.py" in out assert "third" not in out assert "coverage" not in out assert "colorsys" not in out
def test_debug_callers(self): out_lines = self.f1_debug_output(["pid", "dataop", "dataio", "callers"]) print(out_lines) # For every real message, there should be a stack trace with a line like # "f1_debug_output : /Users/ned/coverage/tests/test_debug.py @71" real_messages = re_lines(out_lines, r":\d+", match=False).splitlines() frame_pattern = r"\s+f1_debug_output : .*tests[/\\]test_debug.py:\d+$" frames = re_lines(out_lines, frame_pattern).splitlines() assert len(real_messages) == len(frames) last_line = out_lines.splitlines()[-1] # The details of what to expect on the stack are empirical, and can change # as the code changes. This test is here to ensure that the debug code # continues working. It's ok to adjust these details over time. assert re.search(r"^\s*\d+\.\w{4}: Adding file tracers: 0 files", real_messages[-1]) assert re.search(r"\s+add_file_tracers : .*coverage[/\\]sqldata.py:\d+$", last_line)
def test_debug_trace(self): out_text = self.f1_debug_output(["trace"]) # We should have a line like "Tracing 'f1.py'", perhaps with an # absolute path. assert re.search(r"Tracing '.*f1.py'", out_text) # We should have lines like "Not tracing 'collector.py'..." assert re_lines(r"^Not tracing .*: is part of coverage.py$", out_text)
def test_debug_trace(self): out_lines = self.f1_debug_output(["trace"]) # We should have a line like "Tracing 'f1.py'" assert "Tracing 'f1.py'" in out_lines # We should have lines like "Not tracing 'collector.py'..." coverage_lines = re_lines(out_lines, r"^Not tracing .*: is part of coverage.py$") assert coverage_lines
def test_coverage_run_dir_is_like_python_dir(self): with open(TRY_EXECFILE) as f: self.make_file("with_main/__main__.py", f.read()) out_cov = self.run_command("coverage run with_main") out_py = self.run_command("python with_main") # The coverage.py results are not identical to the Python results, and # I don't know why. For now, ignore those failures. If someone finds # a real problem with the discrepancies, we can work on it some more. ignored = r"__file__|__loader__|__package__" # PyPy includes the current directory in the path when running a # directory, while CPython and coverage.py do not. Exclude that from # the comparison also... if env.PYPY: ignored += "|" + re.escape(os.getcwd()) out_cov = re_lines(out_cov, ignored, match=False) out_py = re_lines(out_py, ignored, match=False) self.assert_tryexecfile_output(out_cov, out_py)
def test_installed_namespace_packages(self, coverage_command): # https://github.com/nedbat/coveragepy/issues/1231 # When namespace packages were installed, they were considered # third-party packages. Test that isn't still happening. out = run_in_venv(coverage_command + " run --source=nspkg myproduct.py") # In particular, this warning doesn't appear: # Already imported a file that will be measured: .../coverage/__main__.py assert out == self.expected_stdout # Check that our tracing was accurate. Files are mentioned because # --source refers to a file. debug_out = self.get_trace_output() assert re_lines( r"^Not tracing .*\bexecfile.py': " + "module 'coverage.execfile' falls outside the --source spec", debug_out, ) assert re_lines( r"^Not tracing .*\bmyproduct.py': module 'myproduct' falls outside the --source spec", debug_out, ) assert re_lines( r"^Not tracing .*\bcolorsys.py': module 'colorsys' falls outside the --source spec", debug_out, ) out = run_in_venv(coverage_command + " report") # Name Stmts Miss Cover # ------------------------------------------------------------------------------ # another_pkg/nspkg/sixth/__init__.py 2 0 100% # venv/lib/python3.9/site-packages/nspkg/fifth/__init__.py 2 0 100% # ------------------------------------------------------------------------------ # TOTAL 4 0 100% assert "myproduct.py" not in out assert "third" not in out assert "coverage" not in out assert "colorsys" not in out assert "fifth" in out assert "sixth" in out
def test_debug_callers(self): out_lines = self.f1_debug_output(["pid", "dataop", "dataio", "callers"]) print(out_lines) # For every real message, there should be a stack trace with a line like # "f1_debug_output : /Users/ned/coverage/tests/test_debug.py @71" real_messages = re_lines(out_lines, r" @\d+", match=False).splitlines() frame_pattern = r"\s+f1_debug_output : .*tests[/\\]test_debug.py @\d+$" frames = re_lines(out_lines, frame_pattern).splitlines() self.assertEqual(len(real_messages), len(frames)) # The last message should be "Writing data", and the last frame should # be _write_file in data.py. last_line = out_lines.splitlines()[-1] from coverage.data import STORAGE if STORAGE == "json": self.assertRegex(real_messages[-1], r"^\s*\d+\.\w{4}: Writing data") self.assertRegex(last_line, r"\s+_write_file : .*coverage[/\\]data.py @\d+$") else: self.assertRegex(real_messages[-1], r"^\s*\d+\.\w{4}: Creating data file") self.assertRegex(last_line, r"\s+_create_db : .*coverage[/\\]sqldata.py @\d+$")
def test_debug_trace(self): out_lines = self.f1_debug_output(["trace"]) # We should have a line like "Tracing 'f1.py'" self.assertIn("Tracing 'f1.py'", out_lines) # We should have lines like "Not tracing 'collector.py'..." coverage_lines = re_lines( out_lines, r"^Not tracing .*: is part of coverage.py$" ) self.assertTrue(coverage_lines)
def test_debug_sys(self): out_lines = self.f1_debug_output(["sys"]) labels = """ version coverage cover_paths pylib_paths tracer configs_attempted config_file configs_read data_file python platform implementation executable pid cwd path environment command_line cover_match pylib_match """.split() for label in labels: label_pat = r"^\s*%s: " % label msg = "Incorrect lines for %r" % label assert 1 == len(re_lines(out_lines, label_pat).splitlines()), msg
def test_debug_sys(self): out_text = self.f1_debug_output(["sys"]) labels = """ coverage_version coverage_module coverage_paths stdlib_paths third_party_paths tracer configs_attempted config_file configs_read data_file python platform implementation executable pid cwd path environment command_line cover_match pylib_match """.split() for label in labels: label_pat = fr"^\s*{label}: " msg = f"Incorrect lines for {label!r}" assert 1 == len(re_lines(label_pat, out_text)), msg
def test_debug_config(self): out_lines = self.f1_debug_output(["config"]) labels = """ attempted_config_files branch config_files cover_pylib data_file debug exclude_list extra_css html_dir html_title ignore_errors include omit parallel partial_always_list partial_list paths precision show_missing source timid xml_output """.split() for label in labels: label_pat = r"^\s*%s: " % label self.assertEqual(len(re_lines(out_lines, label_pat).splitlines()), 1)
def test_debug_config(self): out_lines = self.f1_debug_output(["config"]) labels = """ attempted_config_files branch config_files_read config_file cover_pylib data_file debug exclude_list extra_css html_dir html_title ignore_errors run_include run_omit parallel partial_always_list partial_list paths precision show_missing source timid xml_output report_include report_omit """.split() for label in labels: label_pat = r"^\s*%s: " % label msg = "Incorrect lines for %r" % label assert 1 == len(re_lines(out_lines, label_pat).splitlines()), msg
def test_debug_sys(self): out_lines = self.f1_debug_output(["sys"]) labels = """ version coverage cover_paths pylib_paths tracer configs_attempted config_file configs_read data_file python platform implementation executable pid cwd path environment command_line cover_match pylib_match """.split() for label in labels: label_pat = r"^\s*%s: " % label self.assertEqual( len(re_lines(out_lines, label_pat).splitlines()), 1, msg="Incorrect lines for %r" % label, )
def test_third_party_venv_isnt_measured(self, coverage_command): out = run_in_venv(coverage_command + " run --source=. myproduct.py") # In particular, this warning doesn't appear: # Already imported a file that will be measured: .../coverage/__main__.py assert out == self.expected_stdout # Check that our tracing was accurate. Files are mentioned because # --source refers to a file. debug_out = self.get_trace_output() assert re_lines( r"^Not tracing .*\bexecfile.py': inside --source, but is third-party", debug_out, ) assert re_lines(r"^Tracing .*\bmyproduct.py", debug_out) assert re_lines( r"^Not tracing .*\bcolorsys.py': falls outside the --source spec", debug_out, ) out = run_in_venv(coverage_command + " report") assert "myproduct.py" in out assert "third" not in out assert "coverage" not in out assert "colorsys" not in out
def test_debug_config(self): out_lines = self.f1_debug_output(["config"]) labels = """ attempted_config_files branch config_files_read config_file cover_pylib data_file debug exclude_list extra_css html_dir html_title ignore_errors run_include run_omit parallel partial_always_list partial_list paths precision show_missing source timid xml_output report_include report_omit """.split() for label in labels: label_pat = r"^\s*%s: " % label self.assertEqual( len(re_lines(out_lines, label_pat).splitlines()), 1, msg="Incorrect lines for %r" % label, )
def test_re_lines_inverted(self, pat, text, result): assert re_lines_text(pat, text, match=False) == result assert re_lines(pat, text, match=False) == result.splitlines()
def test_re_lines(text, pat, result): assert re_lines(text, pat) == result
def test_re_lines_inverted(text, pat, result): assert re_lines(text, pat, match=False) == result
def test_re_lines(text, pat, result): assert re_lines(text, pat) == result
def test_re_lines_inverted(text, pat, result): assert re_lines(text, pat, match=False) == result
def test_re_lines(self, pat, text, result): assert re_lines_text(pat, text) == result assert re_lines(pat, text) == result.splitlines()