diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2023-05-13 05:46:46 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2023-05-13 05:46:46 -0400 |
commit | 007323a22836b5e30b5c76cfae650784c05e8584 (patch) | |
tree | 9b1f87e1fa3b7c2506cc35d020d547c37c491dca /tests/test_summary.py | |
parent | 8abc5a12c773bba92c37c22480a8cf3db4ddbbec (diff) | |
download | python-coveragepy-git-007323a22836b5e30b5c76cfae650784c05e8584.tar.gz |
refactor: file names match the commands they implement better
Diffstat (limited to 'tests/test_summary.py')
-rw-r--r-- | tests/test_summary.py | 1081 |
1 files changed, 0 insertions, 1081 deletions
diff --git a/tests/test_summary.py b/tests/test_summary.py deleted file mode 100644 index f2158c93..00000000 --- a/tests/test_summary.py +++ /dev/null @@ -1,1081 +0,0 @@ -# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 -# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt - -"""Test text-based summary reporting for coverage.py""" - -from __future__ import annotations - -import glob -import io -import math -import os -import os.path -import py_compile -import re - -from typing import Tuple - -import pytest - -import coverage -from coverage import env -from coverage.control import Coverage -from coverage.data import CoverageData -from coverage.exceptions import ConfigError, NoDataError, NotPython -from coverage.files import abs_file -from coverage.summary import SummaryReporter -from coverage.types import TConfigValueIn - -from tests.coveragetest import CoverageTest, TESTS_DIR, UsingModulesMixin -from tests.helpers import assert_coverage_warnings - - -class SummaryTest(UsingModulesMixin, CoverageTest): - """Tests of the text summary reporting for coverage.py.""" - - def make_mycode(self) -> None: - """Make the mycode.py file when needed.""" - self.make_file("mycode.py", """\ - import covmod1 - import covmodzip1 - a = 1 - print('done') - """) - - def test_report(self) -> None: - self.make_mycode() - cov = coverage.Coverage() - self.start_import_stop(cov, "mycode") - assert self.stdout() == 'done\n' - report = self.get_report(cov) - - # Name Stmts Miss Cover - # ------------------------------------------------------------------ - # c:/ned/coverage/tests/modules/covmod1.py 2 0 100% - # c:/ned/coverage/tests/zipmods.zip/covmodzip1.py 2 0 100% - # mycode.py 4 0 100% - # ------------------------------------------------------------------ - # TOTAL 8 0 100% - - assert "/coverage/__init__/" not in report - assert "/tests/modules/covmod1.py " in report - assert "/tests/zipmods.zip/covmodzip1.py " in report - assert "mycode.py " in report - assert self.last_line_squeezed(report) == "TOTAL 8 0 100%" - - def test_report_just_one(self) -> None: - # Try reporting just one module - self.make_mycode() - cov = coverage.Coverage() - self.start_import_stop(cov, "mycode") - report = self.get_report(cov, morfs=["mycode.py"]) - - # Name Stmts Miss Cover - # ------------------------------- - # mycode.py 4 0 100% - # ------------------------------- - # TOTAL 4 0 100% - assert self.line_count(report) == 5 - assert "/coverage/" not in report - assert "/tests/modules/covmod1.py " not in report - assert "/tests/zipmods.zip/covmodzip1.py " not in report - assert "mycode.py " in report - assert self.last_line_squeezed(report) == "TOTAL 4 0 100%" - - def test_report_wildcard(self) -> None: - # Try reporting using wildcards to get the modules. - self.make_mycode() - # Wildcard is handled by shell or cmdline.py, so use real commands - self.run_command("coverage run mycode.py") - report = self.report_from_command("coverage report my*.py") - - # Name Stmts Miss Cover - # ------------------------------- - # mycode.py 4 0 100% - # ------------------------------- - # TOTAL 4 0 100% - - assert self.line_count(report) == 5 - assert "/coverage/" not in report - assert "/tests/modules/covmod1.py " not in report - assert "/tests/zipmods.zip/covmodzip1.py " not in report - assert "mycode.py " in report - assert self.last_line_squeezed(report) == "TOTAL 4 0 100%" - - def test_report_omitting(self) -> None: - # Try reporting while omitting some modules - self.make_mycode() - cov = coverage.Coverage() - self.start_import_stop(cov, "mycode") - report = self.get_report(cov, omit=[f"{TESTS_DIR}/*", "*/site-packages/*"]) - - # Name Stmts Miss Cover - # ------------------------------- - # mycode.py 4 0 100% - # ------------------------------- - # TOTAL 4 0 100% - - assert self.line_count(report) == 5 - assert "/coverage/" not in report - assert "/tests/modules/covmod1.py " not in report - assert "/tests/zipmods.zip/covmodzip1.py " not in report - assert "mycode.py " in report - assert self.last_line_squeezed(report) == "TOTAL 4 0 100%" - - def test_report_including(self) -> None: - # Try reporting while including some modules - self.make_mycode() - cov = coverage.Coverage() - self.start_import_stop(cov, "mycode") - report = self.get_report(cov, include=["mycode*"]) - - # Name Stmts Miss Cover - # ------------------------------- - # mycode.py 4 0 100% - # ------------------------------- - # TOTAL 4 0 100% - - assert self.line_count(report) == 5 - assert "/coverage/" not in report - assert "/tests/modules/covmod1.py " not in report - assert "/tests/zipmods.zip/covmodzip1.py " not in report - assert "mycode.py " in report - assert self.last_line_squeezed(report) == "TOTAL 4 0 100%" - - def test_report_include_relative_files_and_path(self) -> None: - """ - Test that when relative_files is True and a relative path to a module - is included, coverage is reported for the module. - - Ref: https://github.com/nedbat/coveragepy/issues/1604 - """ - self.make_mycode() - self.make_file(".coveragerc", """\ - [run] - relative_files = true - """) - self.make_file("submodule/mycode.py", "import mycode") - - cov = coverage.Coverage() - self.start_import_stop(cov, "submodule/mycode") - report = self.get_report(cov, include="submodule/mycode.py") - - # Name Stmts Miss Cover - # --------------------------------------- - # submodule/mycode.py 1 0 100% - # --------------------------------------- - # TOTAL 1 0 100% - - assert "submodule/mycode.py " in report - assert self.last_line_squeezed(report) == "TOTAL 1 0 100%" - - def test_report_include_relative_files_and_wildcard_path(self) -> None: - self.make_mycode() - self.make_file(".coveragerc", """\ - [run] - relative_files = true - """) - self.make_file("submodule/mycode.py", "import nested.submodule.mycode") - self.make_file("nested/submodule/mycode.py", "import mycode") - - cov = coverage.Coverage() - self.start_import_stop(cov, "submodule/mycode") - report = self.get_report(cov, include="*/submodule/mycode.py") - - # Name Stmts Miss Cover - # ------------------------------------------------- - # nested/submodule/mycode.py 1 0 100% - # submodule/mycode.py 1 0 100% - # ------------------------------------------------- - # TOTAL 2 0 100% - - reported_files = [line.split()[0] for line in report.splitlines()[2:4]] - assert reported_files == [ - "nested/submodule/mycode.py", - "submodule/mycode.py", - ] - - def test_omit_files_here(self) -> None: - # https://github.com/nedbat/coveragepy/issues/1407 - self.make_file("foo.py", "") - self.make_file("bar/bar.py", "") - self.make_file("tests/test_baz.py", """\ - def test_foo(): - assert True - test_foo() - """) - self.run_command("coverage run --source=. --omit='./*.py' -m tests.test_baz") - report = self.report_from_command("coverage report") - - # Name Stmts Miss Cover - # --------------------------------------- - # tests/test_baz.py 3 0 100% - # --------------------------------------- - # TOTAL 3 0 100% - - assert self.line_count(report) == 5 - assert "foo" not in report - assert "bar" not in report - assert "tests/test_baz.py" in report - assert self.last_line_squeezed(report) == "TOTAL 3 0 100%" - - def test_run_source_vs_report_include(self) -> None: - # https://github.com/nedbat/coveragepy/issues/621 - self.make_file(".coveragerc", """\ - [run] - source = . - - [report] - include = mod/*,tests/* - """) - # It should be OK to use that configuration. - cov = coverage.Coverage() - with self.assert_warnings(cov, []): - cov.start() - cov.stop() # pragma: nested - - def test_run_omit_vs_report_omit(self) -> None: - # https://github.com/nedbat/coveragepy/issues/622 - # report:omit shouldn't clobber run:omit. - self.make_mycode() - self.make_file(".coveragerc", """\ - [run] - omit = */covmodzip1.py - - [report] - omit = */covmod1.py - """) - self.run_command("coverage run mycode.py") - - # Read the data written, to see that the right files have been omitted from running. - covdata = CoverageData() - covdata.read() - files = [os.path.basename(p) for p in covdata.measured_files()] - assert "covmod1.py" in files - assert "covmodzip1.py" not in files - - def test_report_branches(self) -> None: - self.make_file("mybranch.py", """\ - def branch(x): - if x: - print("x") - return x - branch(1) - """) - cov = coverage.Coverage(source=["."], branch=True) - self.start_import_stop(cov, "mybranch") - assert self.stdout() == 'x\n' - report = self.get_report(cov) - - # Name Stmts Miss Branch BrPart Cover - # ----------------------------------------------- - # mybranch.py 5 0 2 1 86% - # ----------------------------------------------- - # TOTAL 5 0 2 1 86% - assert self.line_count(report) == 5 - assert "mybranch.py " in report - assert self.last_line_squeezed(report) == "TOTAL 5 0 2 1 86%" - - def test_report_show_missing(self) -> None: - self.make_file("mymissing.py", """\ - def missing(x, y): - if x: - print("x") - return x - if y: - print("y") - try: - print("z") - 1/0 - print("Never!") - except ZeroDivisionError: - pass - return x - missing(0, 1) - """) - cov = coverage.Coverage(source=["."]) - self.start_import_stop(cov, "mymissing") - assert self.stdout() == 'y\nz\n' - report = self.get_report(cov, show_missing=True) - - # Name Stmts Miss Cover Missing - # -------------------------------------------- - # mymissing.py 14 3 79% 3-4, 10 - # -------------------------------------------- - # TOTAL 14 3 79% - - assert self.line_count(report) == 5 - squeezed = self.squeezed_lines(report) - assert squeezed[2] == "mymissing.py 14 3 79% 3-4, 10" - assert squeezed[4] == "TOTAL 14 3 79%" - - def test_report_show_missing_branches(self) -> None: - self.make_file("mybranch.py", """\ - def branch(x, y): - if x: - print("x") - if y: - print("y") - branch(1, 1) - """) - cov = coverage.Coverage(branch=True) - self.start_import_stop(cov, "mybranch") - assert self.stdout() == 'x\ny\n' - - def test_report_show_missing_branches_and_lines(self) -> None: - self.make_file("main.py", """\ - import mybranch - """) - self.make_file("mybranch.py", """\ - def branch(x, y, z): - if x: - print("x") - if y: - print("y") - if z: - if x and y: - print("z") - return x - branch(1, 1, 0) - """) - cov = coverage.Coverage(branch=True) - self.start_import_stop(cov, "main") - assert self.stdout() == 'x\ny\n' - - def test_report_skip_covered_no_branches(self) -> None: - self.make_file("main.py", """ - import not_covered - - def normal(): - print("z") - normal() - """) - self.make_file("not_covered.py", """ - def not_covered(): - print("n") - """) - # --fail-under is handled by cmdline.py, use real commands. - out = self.run_command("coverage run main.py") - assert out == "z\n" - report = self.report_from_command("coverage report --skip-covered --fail-under=70") - - # Name Stmts Miss Cover - # ------------------------------------ - # not_covered.py 2 1 50% - # ------------------------------------ - # TOTAL 6 1 83% - # - # 1 file skipped due to complete coverage. - - assert self.line_count(report) == 7, report - squeezed = self.squeezed_lines(report) - assert squeezed[2] == "not_covered.py 2 1 50%" - assert squeezed[4] == "TOTAL 6 1 83%" - assert squeezed[6] == "1 file skipped due to complete coverage." - assert self.last_command_status == 0 - - def test_report_skip_covered_branches(self) -> None: - self.make_file("main.py", """ - import not_covered, covered - - def normal(z): - if z: - print("z") - normal(True) - normal(False) - """) - self.make_file("not_covered.py", """ - def not_covered(n): - if n: - print("n") - not_covered(True) - """) - self.make_file("covered.py", """ - def foo(): - pass - foo() - """) - cov = coverage.Coverage(branch=True) - self.start_import_stop(cov, "main") - assert self.stdout() == "n\nz\n" - report = self.get_report(cov, skip_covered=True) - - # Name Stmts Miss Branch BrPart Cover - # -------------------------------------------------- - # not_covered.py 4 0 2 1 83% - # -------------------------------------------------- - # TOTAL 13 0 4 1 94% - # - # 2 files skipped due to complete coverage. - - assert self.line_count(report) == 7, report - squeezed = self.squeezed_lines(report) - assert squeezed[2] == "not_covered.py 4 0 2 1 83%" - assert squeezed[4] == "TOTAL 13 0 4 1 94%" - assert squeezed[6] == "2 files skipped due to complete coverage." - - def test_report_skip_covered_branches_with_totals(self) -> None: - self.make_file("main.py", """ - import not_covered - import also_not_run - - def normal(z): - if z: - print("z") - normal(True) - normal(False) - """) - self.make_file("not_covered.py", """ - def not_covered(n): - if n: - print("n") - not_covered(True) - """) - self.make_file("also_not_run.py", """ - def does_not_appear_in_this_film(ni): - print("Ni!") - """) - cov = coverage.Coverage(branch=True) - self.start_import_stop(cov, "main") - assert self.stdout() == "n\nz\n" - report = self.get_report(cov, skip_covered=True) - - # Name Stmts Miss Branch BrPart Cover - # -------------------------------------------------- - # also_not_run.py 2 1 0 0 50% - # not_covered.py 4 0 2 1 83% - # -------------------------------------------------- - # TOTAL 13 1 4 1 88% - # - # 1 file skipped due to complete coverage. - - assert self.line_count(report) == 8, report - squeezed = self.squeezed_lines(report) - assert squeezed[2] == "also_not_run.py 2 1 0 0 50%" - assert squeezed[3] == "not_covered.py 4 0 2 1 83%" - assert squeezed[5] == "TOTAL 13 1 4 1 88%" - assert squeezed[7] == "1 file skipped due to complete coverage." - - def test_report_skip_covered_all_files_covered(self) -> None: - self.make_file("main.py", """ - def foo(): - pass - foo() - """) - cov = coverage.Coverage(source=["."], branch=True) - self.start_import_stop(cov, "main") - assert self.stdout() == "" - report = self.get_report(cov, skip_covered=True) - - # Name Stmts Miss Branch BrPart Cover - # ----------------------------------------- - # TOTAL 3 0 0 0 100% - # - # 1 file skipped due to complete coverage. - - assert self.line_count(report) == 5, report - squeezed = self.squeezed_lines(report) - assert squeezed[4] == "1 file skipped due to complete coverage." - - report = self.get_report(cov, squeeze=False, skip_covered=True, output_format="markdown") - - # | Name | Stmts | Miss | Branch | BrPart | Cover | - # |---------- | -------: | -------: | -------: | -------: | -------: | - # | **TOTAL** | **3** | **0** | **0** | **0** | **100%** | - # - # 1 file skipped due to complete coverage. - - assert self.line_count(report) == 5, report - assert report.split("\n")[0] == ( - '| Name | Stmts | Miss | Branch | BrPart | Cover |' - ) - assert report.split("\n")[1] == ( - '|---------- | -------: | -------: | -------: | -------: | -------: |' - ) - assert report.split("\n")[2] == ( - '| **TOTAL** | **3** | **0** | **0** | **0** | **100%** |' - ) - squeezed = self.squeezed_lines(report) - assert squeezed[4] == "1 file skipped due to complete coverage." - - total = self.get_report(cov, output_format="total", skip_covered=True) - assert total == "100\n" - - def test_report_skip_covered_longfilename(self) -> None: - self.make_file("long_______________filename.py", """ - def foo(): - pass - foo() - """) - cov = coverage.Coverage(source=["."], branch=True) - self.start_import_stop(cov, "long_______________filename") - assert self.stdout() == "" - report = self.get_report(cov, squeeze=False, skip_covered=True) - - # Name Stmts Miss Branch BrPart Cover - # ----------------------------------------- - # TOTAL 3 0 0 0 100% - # - # 1 file skipped due to complete coverage. - - assert self.line_count(report) == 5, report - lines = self.report_lines(report) - assert lines[0] == "Name Stmts Miss Branch BrPart Cover" - squeezed = self.squeezed_lines(report) - assert squeezed[4] == "1 file skipped due to complete coverage." - - def test_report_skip_covered_no_data(self) -> None: - cov = coverage.Coverage() - cov.load() - with pytest.raises(NoDataError, match="No data to report."): - self.get_report(cov, skip_covered=True) - self.assert_doesnt_exist(".coverage") - - def test_report_skip_empty(self) -> None: - self.make_file("main.py", """ - import submodule - - def normal(): - print("z") - normal() - """) - self.make_file("submodule/__init__.py", "") - cov = coverage.Coverage() - self.start_import_stop(cov, "main") - assert self.stdout() == "z\n" - report = self.get_report(cov, skip_empty=True) - - # Name Stmts Miss Cover - # ------------------------------------ - # main.py 4 0 100% - # ------------------------------------ - # TOTAL 4 0 100% - # - # 1 empty file skipped. - - assert self.line_count(report) == 7, report - squeezed = self.squeezed_lines(report) - assert squeezed[2] == "main.py 4 0 100%" - assert squeezed[4] == "TOTAL 4 0 100%" - assert squeezed[6] == "1 empty file skipped." - - def test_report_skip_empty_no_data(self) -> None: - self.make_file("__init__.py", "") - cov = coverage.Coverage() - self.start_import_stop(cov, "__init__") - assert self.stdout() == "" - report = self.get_report(cov, skip_empty=True) - - # Name Stmts Miss Cover - # ------------------------------------ - # TOTAL 0 0 100% - # - # 1 empty file skipped. - - assert self.line_count(report) == 5, report - assert report.split("\n")[2] == "TOTAL 0 0 100%" - assert report.split("\n")[4] == "1 empty file skipped." - - def test_report_precision(self) -> None: - self.make_file(".coveragerc", """\ - [report] - precision = 3 - omit = */site-packages/* - """) - self.make_file("main.py", """ - import not_covered, covered - - def normal(z): - if z: - print("z") - normal(True) - normal(False) - """) - self.make_file("not_covered.py", """ - def not_covered(n): - if n: - print("n") - not_covered(True) - """) - self.make_file("covered.py", """ - def foo(): - pass - foo() - """) - cov = coverage.Coverage(branch=True) - self.start_import_stop(cov, "main") - assert self.stdout() == "n\nz\n" - report = self.get_report(cov, squeeze=False) - - # Name Stmts Miss Branch BrPart Cover - # ------------------------------------------------------ - # covered.py 3 0 0 0 100.000% - # main.py 6 0 2 0 100.000% - # not_covered.py 4 0 2 1 83.333% - # ------------------------------------------------------ - # TOTAL 13 0 4 1 94.118% - - assert self.line_count(report) == 7, report - squeezed = self.squeezed_lines(report) - assert squeezed[2] == "covered.py 3 0 0 0 100.000%" - assert squeezed[4] == "not_covered.py 4 0 2 1 83.333%" - assert squeezed[6] == "TOTAL 13 0 4 1 94.118%" - - def test_report_precision_all_zero(self) -> None: - self.make_file("not_covered.py", """ - def not_covered(n): - if n: - print("n") - """) - self.make_file("empty.py", "") - cov = coverage.Coverage(source=["."]) - self.start_import_stop(cov, "empty") - report = self.get_report(cov, precision=6, squeeze=False) - - # Name Stmts Miss Cover - # ----------------------------------------- - # empty.py 0 0 100.000000% - # not_covered.py 3 3 0.000000% - # ----------------------------------------- - # TOTAL 3 3 0.000000% - - assert self.line_count(report) == 6, report - assert "empty.py 0 0 100.000000%" in report - assert "not_covered.py 3 3 0.000000%" in report - assert "TOTAL 3 3 0.000000%" in report - - def test_dotpy_not_python(self) -> None: - # We run a .py file, and when reporting, we can't parse it as Python. - # We should get an error message in the report. - - self.make_data_file(lines={"mycode.py": [1]}) - self.make_file("mycode.py", "This isn't python at all!") - cov = coverage.Coverage() - cov.load() - msg = r"Couldn't parse '.*[/\\]mycode.py' as Python source: '.*' at line 1" - with pytest.raises(NotPython, match=msg): - self.get_report(cov, morfs=["mycode.py"]) - - def test_accented_directory(self) -> None: - # Make a file with a non-ascii character in the directory name. - self.make_file("\xe2/accented.py", "print('accented')") - self.make_data_file(lines={abs_file("\xe2/accented.py"): [1]}) - report_expected = ( - "Name Stmts Miss Cover\n" + - "-----------------------------------\n" + - "\xe2/accented.py 1 0 100%\n" + - "-----------------------------------\n" + - "TOTAL 1 0 100%\n" - ) - cov = coverage.Coverage() - cov.load() - output = self.get_report(cov, squeeze=False) - assert output == report_expected - - def test_accenteddotpy_not_python(self) -> None: - # We run a .py file with a non-ascii name, and when reporting, we can't - # parse it as Python. We should get an error message in the report. - - self.make_data_file(lines={"accented\xe2.py": [1]}) - self.make_file("accented\xe2.py", "This isn't python at all!") - cov = coverage.Coverage() - cov.load() - msg = r"Couldn't parse '.*[/\\]accented\xe2.py' as Python source: '.*' at line 1" - with pytest.raises(NotPython, match=msg): - self.get_report(cov, morfs=["accented\xe2.py"]) - - def test_dotpy_not_python_ignored(self) -> None: - # We run a .py file, and when reporting, we can't parse it as Python, - # but we've said to ignore errors, so there's no error reported, - # though we still get a warning. - self.make_file("mycode.py", "This isn't python at all!") - self.make_data_file(lines={"mycode.py": [1]}) - cov = coverage.Coverage() - cov.load() - with pytest.raises(NoDataError, match="No data to report."): - with pytest.warns(Warning) as warns: - self.get_report(cov, morfs=["mycode.py"], ignore_errors=True) - assert_coverage_warnings( - warns, - re.compile(r"Couldn't parse Python file '.*[/\\]mycode.py' \(couldnt-parse\)"), - ) - - def test_dothtml_not_python(self) -> None: - # We run a .html file, and when reporting, we can't parse it as - # Python. Since it wasn't .py, no error is reported. - - # Pretend to run an html file. - self.make_file("mycode.html", "<h1>This isn't python at all!</h1>") - self.make_data_file(lines={"mycode.html": [1]}) - cov = coverage.Coverage() - cov.load() - with pytest.raises(NoDataError, match="No data to report."): - self.get_report(cov, morfs=["mycode.html"]) - - def test_report_no_extension(self) -> None: - self.make_file("xxx", """\ - # This is a python file though it doesn't look like it, like a main script. - a = b = c = d = 0 - a = 3 - b = 4 - if not b: - c = 6 - d = 7 - print(f"xxx: {a} {b} {c} {d}") - """) - self.make_data_file(lines={abs_file("xxx"): [2, 3, 4, 5, 7, 8]}) - cov = coverage.Coverage() - cov.load() - report = self.get_report(cov) - assert self.last_line_squeezed(report) == "TOTAL 7 1 86%" - - def test_report_with_chdir(self) -> None: - self.make_file("chdir.py", """\ - import os - print("Line One") - os.chdir("subdir") - print("Line Two") - print(open("something").read()) - """) - self.make_file("subdir/something", "hello") - out = self.run_command("coverage run --source=. chdir.py") - assert out == "Line One\nLine Two\nhello\n" - report = self.report_from_command("coverage report") - assert self.last_line_squeezed(report) == "TOTAL 5 0 100%" - report = self.report_from_command("coverage report --format=markdown") - assert self.last_line_squeezed(report) == "| **TOTAL** | **5** | **0** | **100%** |" - - def test_bug_156_file_not_run_should_be_zero(self) -> None: - # https://github.com/nedbat/coveragepy/issues/156 - self.make_file("mybranch.py", """\ - def branch(x): - if x: - print("x") - return x - branch(1) - """) - self.make_file("main.py", """\ - print("y") - """) - cov = coverage.Coverage(branch=True, source=["."]) - self.start_import_stop(cov, "main") - report = self.get_report(cov).splitlines() - assert "mybranch.py 5 5 2 0 0%" in report - - def run_TheCode_and_report_it(self) -> str: - """A helper for the next few tests.""" - cov = coverage.Coverage() - self.start_import_stop(cov, "TheCode") - return self.get_report(cov) - - def test_bug_203_mixed_case_listed_twice_with_rc(self) -> None: - self.make_file("TheCode.py", "a = 1\n") - self.make_file(".coveragerc", "[run]\nsource = .\n") - - report = self.run_TheCode_and_report_it() - assert "TheCode" in report - assert "thecode" not in report - - def test_bug_203_mixed_case_listed_twice(self) -> None: - self.make_file("TheCode.py", "a = 1\n") - - report = self.run_TheCode_and_report_it() - - assert "TheCode" in report - assert "thecode" not in report - - @pytest.mark.skipif(not env.WINDOWS, reason=".pyw files are only on Windows.") - def test_pyw_files(self) -> None: - # https://github.com/nedbat/coveragepy/issues/261 - self.make_file("start.pyw", """\ - import mod - print("In start.pyw") - """) - self.make_file("mod.pyw", """\ - print("In mod.pyw") - """) - cov = coverage.Coverage() - # start_import_stop can't import the .pyw file, so use the long form. - cov.start() - import start # pragma: nested # pylint: disable=import-error, unused-import - cov.stop() # pragma: nested - - report = self.get_report(cov) - assert "NoSource" not in report - report_lines = report.splitlines() - assert "start.pyw 2 0 100%" in report_lines - assert "mod.pyw 1 0 100%" in report_lines - - def test_tracing_pyc_file(self) -> None: - # Create two Python files. - self.make_file("mod.py", "a = 1\n") - self.make_file("main.py", "import mod\n") - - # Make one into a .pyc. - py_compile.compile("mod.py") - - # Run the program. - cov = coverage.Coverage() - self.start_import_stop(cov, "main") - - report_lines = self.get_report(cov).splitlines() - assert "mod.py 1 0 100%" in report_lines - report = self.get_report(cov, squeeze=False, output_format="markdown") - assert report.split("\n")[3] == "| mod.py | 1 | 0 | 100% |" - assert report.split("\n")[4] == "| **TOTAL** | **2** | **0** | **100%** |" - - def test_missing_py_file_during_run(self) -> None: - # Create two Python files. - self.make_file("mod.py", "a = 1\n") - self.make_file("main.py", "import mod\n") - - # Make one into a .pyc, and remove the .py. - py_compile.compile("mod.py") - os.remove("mod.py") - - # Python 3 puts the .pyc files in a __pycache__ directory, and will - # not import from there without source. It will import a .pyc from - # the source location though. - pycs = glob.glob("__pycache__/mod.*.pyc") - assert len(pycs) == 1 - os.rename(pycs[0], "mod.pyc") - - # Run the program. - cov = coverage.Coverage() - self.start_import_stop(cov, "main") - - # Put back the missing Python file. - self.make_file("mod.py", "a = 1\n") - report = self.get_report(cov).splitlines() - assert "mod.py 1 0 100%" in report - - def test_empty_files(self) -> None: - # Shows that empty files like __init__.py are listed as having zero - # statements, not one statement. - cov = coverage.Coverage(branch=True) - cov.start() - import usepkgs # pragma: nested # pylint: disable=import-error, unused-import - cov.stop() # pragma: nested - report = self.get_report(cov) - assert "tests/modules/pkg1/__init__.py 1 0 0 0 100%" in report - assert "tests/modules/pkg2/__init__.py 0 0 0 0 100%" in report - report = self.get_report(cov, squeeze=False, output_format="markdown") - # get_report() escapes backslash so we expect forward slash escaped - # underscore - assert "tests/modules/pkg1//_/_init/_/_.py " in report - assert "| 1 | 0 | 0 | 0 | 100% |" in report - assert "tests/modules/pkg2//_/_init/_/_.py " in report - assert "| 0 | 0 | 0 | 0 | 100% |" in report - - def test_markdown_with_missing(self) -> None: - self.make_file("mymissing.py", """\ - def missing(x, y): - if x: - print("x") - return x - if y: - print("y") - try: - print("z") - 1/0 - print("Never!") - except ZeroDivisionError: - pass - return x - missing(0, 1) - """) - cov = coverage.Coverage(source=["."]) - self.start_import_stop(cov, "mymissing") - assert self.stdout() == 'y\nz\n' - report = self.get_report(cov, squeeze=False, output_format="markdown", show_missing=True) - - # | Name | Stmts | Miss | Cover | Missing | - # |------------- | -------: | -------: | ------: | --------: | - # | mymissing.py | 14 | 3 | 79% | 3-4, 10 | - # | **TOTAL** | **14** | **3** | **79%** | | - assert self.line_count(report) == 4 - report_lines = report.split("\n") - assert report_lines[2] == "| mymissing.py | 14 | 3 | 79% | 3-4, 10 |" - assert report_lines[3] == "| **TOTAL** | **14** | **3** | **79%** | |" - - assert self.get_report(cov, output_format="total") == "79\n" - assert self.get_report(cov, output_format="total", precision=2) == "78.57\n" - assert self.get_report(cov, output_format="total", precision=4) == "78.5714\n" - - def test_bug_1524(self) -> None: - self.make_file("bug1524.py", """\ - class Mine: - @property - def thing(self) -> int: - return 17 - - print(Mine().thing) - """) - cov = coverage.Coverage() - self.start_import_stop(cov, "bug1524") - assert self.stdout() == "17\n" - report = self.get_report(cov) - report_lines = report.splitlines() - assert report_lines[2] == "bug1524.py 5 0 100%" - - -class ReportingReturnValueTest(CoverageTest): - """Tests of reporting functions returning values.""" - - def run_coverage(self) -> Coverage: - """Run coverage on doit.py and return the coverage object.""" - self.make_file("doit.py", """\ - a = 1 - b = 2 - c = 3 - d = 4 - if a > 10: - f = 6 - g = 7 - """) - - cov = coverage.Coverage() - self.start_import_stop(cov, "doit") - return cov - - def test_report(self) -> None: - cov = self.run_coverage() - val = cov.report(include="*/doit.py") - assert math.isclose(val, 6 / 7 * 100) - - def test_html(self) -> None: - cov = self.run_coverage() - val = cov.html_report(include="*/doit.py") - assert math.isclose(val, 6 / 7 * 100) - - def test_xml(self) -> None: - cov = self.run_coverage() - val = cov.xml_report(include="*/doit.py") - assert math.isclose(val, 6 / 7 * 100) - - -class SummaryReporterConfigurationTest(CoverageTest): - """Tests of SummaryReporter.""" - - def make_rigged_file(self, filename: str, stmts: int, miss: int) -> None: - """Create a file that will have specific results. - - `stmts` and `miss` are ints, the number of statements, and - missed statements that should result. - """ - run = stmts - miss - 1 - dont_run = miss - source = "" - source += "a = 1\n" * run - source += "if a == 99:\n" - source += " a = 2\n" * dont_run - self.make_file(filename, source) - - def get_summary_text(self, *options: Tuple[str, TConfigValueIn]) -> str: - """Get text output from the SummaryReporter. - - The arguments are tuples: (name, value) for Coverage.set_option. - """ - self.make_rigged_file("file1.py", 339, 155) - self.make_rigged_file("file2.py", 13, 3) - self.make_rigged_file("file10.py", 234, 228) - self.make_file("doit.py", "import file1, file2, file10") - - cov = Coverage(source=["."], omit=["doit.py"]) - self.start_import_stop(cov, "doit") - for name, value in options: - cov.set_option(name, value) - printer = SummaryReporter(cov) - destination = io.StringIO() - printer.report([], destination) - return destination.getvalue() - - def test_test_data(self) -> None: - # We use our own test files as test data. Check that our assumptions - # about them are still valid. We want the three columns of numbers to - # sort in three different orders. - report = self.get_summary_text() - # Name Stmts Miss Cover - # ------------------------------ - # file1.py 339 155 54% - # file2.py 13 3 77% - # file10.py 234 228 3% - # ------------------------------ - # TOTAL 586 386 34% - lines = report.splitlines()[2:-2] - assert len(lines) == 3 - nums = [list(map(int, l.replace('%', '').split()[1:])) for l in lines] - # [ - # [339, 155, 54], - # [ 13, 3, 77], - # [234, 228, 3] - # ] - assert nums[1][0] < nums[2][0] < nums[0][0] - assert nums[1][1] < nums[0][1] < nums[2][1] - assert nums[2][2] < nums[0][2] < nums[1][2] - - def test_defaults(self) -> None: - """Run the report with no configuration options.""" - report = self.get_summary_text() - assert 'Missing' not in report - assert 'Branch' not in report - - def test_print_missing(self) -> None: - """Run the report printing the missing lines.""" - report = self.get_summary_text(('report:show_missing', True)) - assert 'Missing' in report - assert 'Branch' not in report - - def assert_ordering(self, text: str, *words: str) -> None: - """Assert that the `words` appear in order in `text`.""" - indexes = list(map(text.find, words)) - assert -1 not in indexes - msg = f"The words {words!r} don't appear in order in {text!r}" - assert indexes == sorted(indexes), msg - - def test_default_sort_report(self) -> None: - # Sort the text report by the default (Name) column. - report = self.get_summary_text() - self.assert_ordering(report, "file1.py", "file2.py", "file10.py") - - def test_sort_report_by_name(self) -> None: - # Sort the text report explicitly by the Name column. - report = self.get_summary_text(('report:sort', 'Name')) - self.assert_ordering(report, "file1.py", "file2.py", "file10.py") - - def test_sort_report_by_stmts(self) -> None: - # Sort the text report by the Stmts column. - report = self.get_summary_text(('report:sort', 'Stmts')) - self.assert_ordering(report, "file2.py", "file10.py", "file1.py") - - def test_sort_report_by_missing(self) -> None: - # Sort the text report by the Missing column. - report = self.get_summary_text(('report:sort', 'Miss')) - self.assert_ordering(report, "file2.py", "file1.py", "file10.py") - - def test_sort_report_by_cover(self) -> None: - # Sort the text report by the Cover column. - report = self.get_summary_text(('report:sort', 'Cover')) - self.assert_ordering(report, "file10.py", "file1.py", "file2.py") - - def test_sort_report_by_cover_plus(self) -> None: - # Sort the text report by the Cover column, including the explicit + sign. - report = self.get_summary_text(('report:sort', '+Cover')) - self.assert_ordering(report, "file10.py", "file1.py", "file2.py") - - def test_sort_report_by_cover_reversed(self) -> None: - # Sort the text report by the Cover column reversed. - report = self.get_summary_text(('report:sort', '-Cover')) - self.assert_ordering(report, "file2.py", "file1.py", "file10.py") - - def test_sort_report_by_invalid_option(self) -> None: - # Sort the text report by a nonsense column. - msg = "Invalid sorting option: 'Xyzzy'" - with pytest.raises(ConfigError, match=msg): - self.get_summary_text(('report:sort', 'Xyzzy')) - - def test_report_with_invalid_format(self) -> None: - # Ask for an invalid format. - msg = "Unknown report format choice: 'xyzzy'" - with pytest.raises(ConfigError, match=msg): - self.get_summary_text(('report:format', 'xyzzy')) |