def test_plugin2(self): self.make_render_and_caller() cov = coverage.Coverage(omit=["*quux*"]) CheckUniqueFilenames.hook(cov, '_should_trace') CheckUniqueFilenames.hook(cov, '_check_include_omit_etc') cov.set_option("run:plugins", ["tests.plugin2"]) self.start_import_stop(cov, "caller") # The way plugin2 works, a file named foo_7.html will be claimed to # have 7 lines in it. If render() was called with line number 4, # then the plugin will claim that lines 4 and 5 were executed. _, statements, missing, _ = cov.analysis("foo_7.html") self.assertEqual(statements, [1, 2, 3, 4, 5, 6, 7]) self.assertEqual(missing, [1, 2, 3, 6, 7]) self.assertIn("foo_7.html", line_counts(cov.get_data())) _, statements, missing, _ = cov.analysis("bar_4.html") self.assertEqual(statements, [1, 2, 3, 4]) self.assertEqual(missing, [1, 4]) self.assertIn("bar_4.html", line_counts(cov.get_data())) self.assertNotIn("quux_5.html", line_counts(cov.get_data())) _, statements, missing, _ = cov.analysis("uni_3.html") self.assertEqual(statements, [1, 2, 3]) self.assertEqual(missing, [1]) self.assertIn("uni_3.html", line_counts(cov.get_data()))
def coverage_usepkgs(self, **kwargs): """Run coverage on usepkgs and return the line summary. Arguments are passed to the `coverage.Coverage` constructor. """ cov = coverage.Coverage(**kwargs) cov.start() import usepkgs # pragma: nested # pylint: disable=import-error, unused-import cov.stop() # pragma: nested data = cov.get_data() summary = line_counts(data) for k, v in list(summary.items()): assert k.endswith(".py") summary[k[:-3]] = v return summary
def do_debug(self, args): """Implementation of 'coverage debug'.""" if not args: show_help( "What information would you like: config, data, sys, premain?") return ERR for info in args: if info == 'sys': sys_info = self.coverage.sys_info() print(info_header("sys")) for line in info_formatter(sys_info): print(" %s" % line) elif info == 'data': self.coverage.load() data = self.coverage.get_data() print(info_header("data")) print("path: %s" % self.coverage.get_data().data_filename()) if data: print("has_arcs: %r" % data.has_arcs()) summary = line_counts(data, fullpath=True) filenames = sorted(summary.keys()) print("\n%d files:" % len(filenames)) for f in filenames: line = "%s: %d lines" % (f, summary[f]) plugin = data.file_tracer(f) if plugin: line += " [%s]" % plugin print(line) else: print("No data collected") elif info == 'config': print(info_header("config")) config_info = self.coverage.config.__dict__.items() for line in info_formatter(config_info): print(" %s" % line) elif info == "premain": print(info_header("premain")) from coverage.debug import short_stack print(short_stack()) else: show_help("Don't know what you mean by %r" % info) return ERR return OK
def do_debug(self, args): """Implementation of 'coverage debug'.""" if not args: show_help( "What information would you like: config, data, sys, premain?") return ERR for info in args: if info == 'sys': sys_info = self.coverage.sys_info() print(info_header("sys")) for line in info_formatter(sys_info): print(f" {line}") elif info == 'data': self.coverage.load() data = self.coverage.get_data() print(info_header("data")) print(f"path: {data.data_filename()}") if data: print(f"has_arcs: {data.has_arcs()!r}") summary = line_counts(data, fullpath=True) filenames = human_sorted(summary.keys()) print(f"\n{len(filenames)} files:") for f in filenames: line = f"{f}: {summary[f]} lines" plugin = data.file_tracer(f) if plugin: line += f" [{plugin}]" print(line) else: print("No data collected") elif info == 'config': print(info_header("config")) config_info = self.coverage.config.__dict__.items() for line in info_formatter(config_info): print(f" {line}") elif info == "premain": print(info_header("premain")) print(short_stack()) else: show_help(f"Don't know what you mean by {info!r}") return ERR return OK
def test_append_data(self): self.make_b_or_c_py() out = self.run_command("coverage run b_or_c.py b") assert out == 'done\n' self.assert_exists(".coverage") self.assert_file_count(".coverage.*", 0) out = self.run_command("coverage run --append b_or_c.py c") assert out == 'done\n' self.assert_exists(".coverage") self.assert_file_count(".coverage.*", 0) # Read the coverage file and see that b_or_c.py has all 8 lines # executed. data = coverage.CoverageData() data.read() assert line_counts(data)['b_or_c.py'] == 8
def test_combine_with_rc(self): self.make_b_or_c_py() self.make_file(".coveragerc", """\ [run] source = . parallel = true """) out = self.run_command("coverage run b_or_c.py b") assert out == 'done\n' self.assert_doesnt_exist(".coverage") out = self.run_command("coverage run b_or_c.py c") assert out == 'done\n' self.assert_doesnt_exist(".coverage") # After two runs, there should be two .coverage.machine.123 files. self.assert_file_count(".coverage.*", 2) # Combine the parallel coverage data files into .coverage . self.run_command("coverage combine") self.assert_exists(".coverage") self.assert_exists(".coveragerc") # After combining, there should be only the .coverage file. self.assert_file_count(".coverage.*", 0) # Read the coverage file and see that b_or_c.py has all 8 lines # executed. data = coverage.CoverageData() data.read() assert line_counts(data)['b_or_c.py'] == 8 # Reporting should still work even with the .rc file out = self.run_command("coverage report") assert out == textwrap.dedent("""\ Name Stmts Miss Cover ------------------------------- b_or_c.py 8 0 100% ------------------------------- TOTAL 8 0 100% """)
def test_fork(self): self.make_file("fork.py", """\ import os def child(): print('Child!') def main(): ret = os.fork() if ret == 0: child() else: os.waitpid(ret, 0) main() """) out = self.run_command("coverage run -p fork.py") assert out == 'Child!\n' self.assert_doesnt_exist(".coverage") # After running the forking program, there should be two # .coverage.machine.123 files. self.assert_file_count(".coverage.*", 2) # The two data files should have different random numbers at the end of # the file name. data_files = glob.glob(".coverage.*") nums = {name.rpartition(".")[-1] for name in data_files} assert len(nums) == 2, f"Same random: {data_files}" # Combine the parallel coverage data files into .coverage . self.run_command("coverage combine") self.assert_exists(".coverage") # After combining, there should be only the .coverage file. self.assert_file_count(".coverage.*", 0) data = coverage.CoverageData() data.read() assert line_counts(data)['fork.py'] == 9
def test_fullcoverage(self): # fullcoverage is a trick to get stdlib modules measured from # the very beginning of the process. Here we import os and # then check how many lines are measured. self.make_file("getenv.py", """\ import os print("FOOEY == %s" % os.getenv("FOOEY")) """) fullcov = os.path.join(os.path.dirname(coverage.__file__), "fullcoverage") self.set_environ("FOOEY", "BOO") self.set_environ("PYTHONPATH", fullcov) out = self.run_command("python -X frozen_modules=off -m coverage run -L getenv.py") assert out == "FOOEY == BOO\n" data = coverage.CoverageData() data.read() # The actual number of executed lines in os.py when it's # imported is 120 or so. Just running os.getenv executes # about 5. assert line_counts(data)['os.py'] > 50
def do_debug(self, args): """Implementation of 'coverage debug'.""" if not args: show_help("What information would you like: config, data, sys?") return ERR for info in args: if info == 'sys': sys_info = self.coverage.sys_info() print(info_header("sys")) for line in info_formatter(sys_info): print(" %s" % line) elif info == 'data': self.coverage.load() data = self.coverage.get_data() print(info_header("data")) print("path: %s" % self.coverage.get_data().data_filename()) if data: print("has_arcs: %r" % data.has_arcs()) summary = line_counts(data, fullpath=True) filenames = sorted(summary.keys()) print("\n%d files:" % len(filenames)) for f in filenames: line = "%s: %d lines" % (f, summary[f]) plugin = data.file_tracer(f) if plugin: line += " [%s]" % plugin print(line) else: print("No data collected") elif info == 'config': print(info_header("config")) config_info = self.coverage.config.__dict__.items() for line in info_formatter(config_info): print(" %s" % line) else: show_help("Don't know what you mean by %r" % info) return ERR return OK
def try_some_code(self, code, concurrency, the_module, expected_out=None): """Run some concurrency testing code and see that it was all covered. `code` is the Python code to execute. `concurrency` is the name of the concurrency regime to test it under. `the_module` is the imported module that must be available for this to work at all. `expected_out` is the text we expect the code to produce. """ self.make_file("try_it.py", code) cmd = "coverage run --concurrency=%s try_it.py" % concurrency out = self.run_command(cmd) expected_cant_trace = cant_trace_msg(concurrency, the_module) if expected_cant_trace is not None: self.assertEqual(out, expected_cant_trace) else: # We can fully measure the code if we are using the C tracer, which # can support all the concurrency, or if we are using threads. if expected_out is None: expected_out = "%d\n" % (sum(range(self.QLIMIT))) print(code) self.assertEqual(out, expected_out) # Read the coverage file and see that try_it.py has all its lines # executed. data = coverage.CoverageData(".coverage") data.read() # If the test fails, it's helpful to see this info: fname = abs_file("try_it.py") linenos = data.lines(fname) print("{0}: {1}".format(len(linenos), linenos)) print_simple_annotation(code, linenos) lines = line_count(code) self.assertEqual(line_counts(data)['try_it.py'], lines)
def try_some_code(self, code, concurrency, the_module, expected_out=None): """Run some concurrency testing code and see that it was all covered. `code` is the Python code to execute. `concurrency` is the name of the concurrency regime to test it under. `the_module` is the imported module that must be available for this to work at all. `expected_out` is the text we expect the code to produce. """ self.make_file("try_it.py", code) cmd = "coverage run --concurrency=%s try_it.py" % concurrency out = self.run_command(cmd) expected_cant_trace = cant_trace_msg(concurrency, the_module) if expected_cant_trace is not None: assert out == expected_cant_trace else: # We can fully measure the code if we are using the C tracer, which # can support all the concurrency, or if we are using threads. if expected_out is None: expected_out = "%d\n" % (sum(range(self.QLIMIT))) print(code) assert out == expected_out # Read the coverage file and see that try_it.py has all its lines # executed. data = coverage.CoverageData(".coverage") data.read() # If the test fails, it's helpful to see this info: fname = abs_file("try_it.py") linenos = data.lines(fname) print(f"{len(linenos)}: {linenos}") print_simple_annotation(code, linenos) lines = line_count(code) assert line_counts(data)['try_it.py'] == lines
def test_append_data_with_different_file(self): self.make_b_or_c_py() self.make_file(".coveragerc", """\ [run] data_file = .mycovdata """) out = self.run_command("coverage run b_or_c.py b") assert out == 'done\n' self.assert_doesnt_exist(".coverage") self.assert_exists(".mycovdata") out = self.run_command("coverage run --append b_or_c.py c") assert out == 'done\n' self.assert_doesnt_exist(".coverage") self.assert_exists(".mycovdata") # Read the coverage file and see that b_or_c.py has all 8 lines # executed. data = coverage.CoverageData(".mycovdata") data.read() assert line_counts(data)['b_or_c.py'] == 8
def test_subprocess_with_pth_files(self): # An existing data file should not be read when a subprocess gets # measured automatically. Create the data file here with bogus data in # it. data = coverage.CoverageData(".mycovdata") data.add_lines({os.path.abspath('sub.py'): range(100)}) data.write() self.make_file("coverage.ini", """\ [run] data_file = .mycovdata """) self.set_environ("COVERAGE_PROCESS_START", "coverage.ini") import main # pylint: disable=unused-import, import-error with open("out.txt") as f: assert f.read() == "Hello, world!\n" # Read the data from .coverage self.assert_exists(".mycovdata") data = coverage.CoverageData(".mycovdata") data.read() assert line_counts(data)['sub.py'] == 3
def assert_line_counts(self, covdata, counts, fullpath=False): """Check that the line_counts of `covdata` is `counts`.""" self.assertEqual(line_counts(covdata, fullpath), counts)
def assert_line_counts(self, covdata, counts, fullpath=False): """Check that the line_counts of `covdata` is `counts`.""" assert line_counts(covdata, fullpath) == counts
def test_pth_and_source_work_together(self, dashm, package, source): """Run the test for a particular combination of factors. The arguments are all strings: * `dashm`: Either "" (run the program as a file) or "-m" (run the program as a module). * `package`: Either "" (put the source at the top level) or a package name to use to hold the source. * `source`: Either "main" or "sub", which file to use as the ``--source`` argument. """ def fullname(modname): """What is the full module name for `modname` for this test?""" if package and dashm: return '.'.join((package, modname)) else: return modname def path(basename): """Where should `basename` be created for this test?""" return os.path.join(package, basename) # Main will run sub.py. self.make_file(path("main.py"), """\ import %s a = 2 b = 3 """ % fullname('sub')) if package: self.make_file(path("__init__.py"), "") # sub.py will write a few lines. self.make_file(path("sub.py"), """\ # Avoid 'with' so Jython can play along. f = open("out.txt", "w") f.write("Hello, world!") f.close() """) self.make_file("coverage.ini", """\ [run] source = %s """ % fullname(source)) self.set_environ("COVERAGE_PROCESS_START", "coverage.ini") if dashm: cmd = "python -m %s" % fullname('main') else: cmd = "python %s" % path('main.py') self.run_command(cmd) with open("out.txt") as f: assert f.read() == "Hello, world!" # Read the data from .coverage self.assert_exists(".coverage") data = coverage.CoverageData() data.read() summary = line_counts(data) assert summary[source + '.py'] == 3 assert len(summary) == 1