From 9162ad085c0e4a3b3e14fd1fcbdbf65c93b81487 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Fri, 26 Nov 2021 11:21:11 -0500 Subject: [PATCH] test(refactor): avoid full commands to speed tests Also btw, I think some of these tests are duplicative. --- tests/test_api.py | 188 +++++++++++++++++++++++++++++++++++++- tests/test_process.py | 203 ++---------------------------------------- 2 files changed, 192 insertions(+), 199 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index cd6790a73..4c0fe66cf 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -422,7 +422,7 @@ def test_combining_corrupt_data(self): self.make_file(".coverage.foo", """La la la, this isn't coverage data!""") cov = coverage.Coverage() warning_regex = ( - r"Couldn't use data file '.*\.coverage\.foo': file (is encrypted or )?is not a database" + r"Couldn't use data file '.*\.coverage\.foo': file is not a database" ) with self.assert_warnings(cov, [warning_regex]): cov.combine() @@ -1234,3 +1234,189 @@ def test_combine_no_suffix_multiprocessing(self): cov.save() self.assert_file_count(".coverage.*", 0) self.assert_exists(".coverage") + + +class CombiningTest(CoverageTest): + """More tests of combining data.""" + + B_LINES = {"b_or_c.py": [1, 2, 3, 4, 8, 9]} + C_LINES = {"b_or_c.py": [1, 2, 3, 6, 7, 8, 9]} + + def make_b_or_c_py(self): + """Create b_or_c.py, used in a few of these tests.""" + # "b_or_c.py b" will run 6 lines. + # "b_or_c.py c" will run 7 lines. + # Together, they run 8 lines. + self.make_file("b_or_c.py", """\ + import sys + a = 2 + if sys.argv[1] == 'b': + b = 4 + else: + c = 6 + c2 = 7 + d = 8 + print('done') + """) + + def test_combine_parallel_data(self): + self.make_b_or_c_py() + self.make_data_file(".coverage.b", lines=self.B_LINES) + self.make_data_file(".coverage.c", lines=self.C_LINES) + + # Combine the parallel coverage data files into .coverage . + cov = coverage.Coverage() + cov.combine(strict=True) + self.assert_exists(".coverage") + + # 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 + + # Running combine again should fail, because there are no parallel data + # files to combine. + cov = coverage.Coverage() + with pytest.raises(NoDataError, match=r"No data to combine"): + cov.combine(strict=True) + + # And the originally combined data is still there. + data = coverage.CoverageData() + data.read() + assert line_counts(data)['b_or_c.py'] == 8 + + def test_combine_parallel_data_with_a_corrupt_file(self): + self.make_b_or_c_py() + self.make_data_file(".coverage.b", lines=self.B_LINES) + self.make_data_file(".coverage.c", lines=self.C_LINES) + + # Make a bogus data file. + self.make_file(".coverage.bad", "This isn't a coverage data file.") + + # Combine the parallel coverage data files into .coverage . + cov = coverage.Coverage() + with pytest.warns(Warning) as warns: + cov.combine(strict=True) + assert_coverage_warnings( + warns, + re.compile( + r"Couldn't use data file '.*[/\\]\.coverage\.bad': file is not a database" + ), + ) + + # After combining, those two should be the only data files. + self.assert_exists(".coverage") + self.assert_exists(".coverage.bad") + self.assert_file_count(".coverage.*", 1) + + # 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_no_usable_files(self): + # https://github.com/nedbat/coveragepy/issues/629 + self.make_b_or_c_py() + self.make_data_file(".coverage", lines=self.B_LINES) + + # Make bogus data files. + self.make_file(".coverage.bad1", "This isn't a coverage data file.") + self.make_file(".coverage.bad2", "This isn't a coverage data file.") + + # Combine the parallel coverage data files into .coverage, but nothing is readable. + cov = coverage.Coverage() + with pytest.warns(Warning) as warns: + with pytest.raises(NoDataError, match=r"No usable data files"): + cov.combine(strict=True) + + warn_rx = re.compile( + r"Couldn't use data file '.*[/\\]\.coverage\.bad[12]': file is not a database" + ) + assert_coverage_warnings(warns, warn_rx, warn_rx) + + # After combining, we should have a main file and two parallel files. + self.assert_exists(".coverage") + self.assert_exists(".coverage.bad1") + self.assert_exists(".coverage.bad2") + self.assert_file_count(".coverage.*", 2) + + # Read the coverage file and see that b_or_c.py has 6 lines + # executed (we only did b, not c). + data = coverage.CoverageData() + data.read() + assert line_counts(data)['b_or_c.py'] == 6 + + def test_combine_parallel_data_in_two_steps(self): + self.make_b_or_c_py() + self.make_data_file(".coverage.b", lines=self.B_LINES) + + # Combine the (one) parallel coverage data file into .coverage . + cov = coverage.Coverage() + cov.combine(strict=True) + + self.assert_exists(".coverage") + self.assert_file_count(".coverage.*", 0) + + self.make_data_file(".coverage.c", lines=self.C_LINES) + self.assert_exists(".coverage") + self.assert_file_count(".coverage.*", 1) + + # Combine the parallel coverage data files into .coverage . + cov = coverage.Coverage() + cov.load() + cov.combine(strict=True) + + # After combining, there should be only the .coverage file. + 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_parallel_data_no_append(self): + self.make_b_or_c_py() + self.make_data_file(".coverage.b", lines=self.B_LINES) + + # Combine the (one) parallel coverage data file into .coverage . + cov = coverage.Coverage() + cov.combine(strict=True) + self.assert_exists(".coverage") + self.assert_file_count(".coverage.*", 0) + + self.make_data_file(".coverage.c", lines=self.C_LINES) + + # Combine the parallel coverage data files into .coverage, but don't + # use the data in .coverage already. + cov = coverage.Coverage() + cov.combine(strict=True) + + # After combining, there should be only the .coverage file. + self.assert_exists(".coverage") + self.assert_file_count(".coverage.*", 0) + + # Read the coverage file and see that b_or_c.py has only 7 lines + # because we didn't keep the data from running b. + data = coverage.CoverageData() + data.read() + assert line_counts(data)['b_or_c.py'] == 7 + + def test_combine_parallel_data_keep(self): + self.make_b_or_c_py() + self.make_data_file(".coverage.b", lines=self.B_LINES) + self.make_data_file(".coverage.c", lines=self.C_LINES) + + # Combine the parallel coverage data files into .coverage with the keep flag. + cov = coverage.Coverage() + cov.combine(strict=True, keep=True) + + # After combining, the .coverage file & the original combined file should still be there. + self.assert_exists(".coverage") + self.assert_file_count(".coverage.*", 2) diff --git a/tests/test_process.py b/tests/test_process.py index 567f9ace1..fdd71f0f3 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -71,209 +71,16 @@ def make_b_or_c_py(self): # Together, they run 8 lines. self.make_file("b_or_c.py", """\ import sys - a = 1 + a = 2 if sys.argv[1] == 'b': - b = 1 + b = 4 else: - c = 1 - c2 = 2 - d = 1 + c = 6 + c2 = 7 + d = 8 print('done') """) - def test_combine_parallel_data(self): - self.make_b_or_c_py() - out = self.run_command("coverage run -p b_or_c.py b") - assert out == 'done\n' - self.assert_doesnt_exist(".coverage") - self.assert_file_count(".coverage.*", 1) - - out = self.run_command("coverage run -p b_or_c.py c") - assert out == 'done\n' - self.assert_doesnt_exist(".coverage") - - # After two -p 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") - - # 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 - - # Running combine again should fail, because there are no parallel data - # files to combine. - status, out = self.run_command_status("coverage combine") - assert status == 1 - assert out == "No data to combine\n" - - # And the originally combined data is still there. - data = coverage.CoverageData() - data.read() - assert line_counts(data)['b_or_c.py'] == 8 - - def test_combine_parallel_data_with_a_corrupt_file(self): - self.make_b_or_c_py() - out = self.run_command("coverage run -p b_or_c.py b") - assert out == 'done\n' - self.assert_doesnt_exist(".coverage") - self.assert_file_count(".coverage.*", 1) - - out = self.run_command("coverage run -p b_or_c.py c") - assert out == 'done\n' - self.assert_doesnt_exist(".coverage") - - # After two -p runs, there should be two .coverage.machine.123 files. - self.assert_file_count(".coverage.*", 2) - - # Make a bogus data file. - self.make_file(".coverage.bad", "This isn't a coverage data file.") - - # Combine the parallel coverage data files into .coverage . - out = self.run_command("coverage combine") - self.assert_exists(".coverage") - self.assert_exists(".coverage.bad") - warning_regex = ( - r"CoverageWarning: Couldn't use data file '.*\.coverage\.bad': " + - r"file (is encrypted or )?is not a database" - ) - assert re.search(warning_regex, out) - - # After combining, those two should be the only data files. - self.assert_file_count(".coverage.*", 1) - - # 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_no_usable_files(self): - # https://github.com/nedbat/coveragepy/issues/629 - 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) - - # Make bogus data files. - self.make_file(".coverage.bad1", "This isn't a coverage data file.") - self.make_file(".coverage.bad2", "This isn't a coverage data file.") - - # Combine the parallel coverage data files into .coverage, but nothing is readable. - status, out = self.run_command_status("coverage combine") - assert status == 1 - - for n in "12": - self.assert_exists(f".coverage.bad{n}") - warning_regex = ( - fr"CoverageWarning: Couldn't use data file '.*\.coverage.bad{n}': " + - r"file (is encrypted or )?is not a database" - ) - assert re.search(warning_regex, out) - assert re.search(r"No usable data files", out) - - # After combining, we should have a main file and two parallel files. - self.assert_exists(".coverage") - self.assert_file_count(".coverage.*", 2) - - # Read the coverage file and see that b_or_c.py has 6 lines - # executed (we only did b, not c). - data = coverage.CoverageData() - data.read() - assert line_counts(data)['b_or_c.py'] == 6 - - def test_combine_parallel_data_in_two_steps(self): - self.make_b_or_c_py() - - out = self.run_command("coverage run -p b_or_c.py b") - assert out == 'done\n' - self.assert_doesnt_exist(".coverage") - self.assert_file_count(".coverage.*", 1) - - # Combine the (one) parallel coverage data file into .coverage . - self.run_command("coverage combine") - self.assert_exists(".coverage") - self.assert_file_count(".coverage.*", 0) - - out = self.run_command("coverage run -p b_or_c.py c") - assert out == 'done\n' - self.assert_exists(".coverage") - self.assert_file_count(".coverage.*", 1) - - # Combine the parallel coverage data files into .coverage . - self.run_command("coverage combine --append") - self.assert_exists(".coverage") - - # 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 - - def test_combine_parallel_data_no_append(self): - self.make_b_or_c_py() - - out = self.run_command("coverage run -p b_or_c.py b") - assert out == 'done\n' - self.assert_doesnt_exist(".coverage") - self.assert_file_count(".coverage.*", 1) - - # Combine the (one) parallel coverage data file into .coverage . - self.run_command("coverage combine") - self.assert_exists(".coverage") - self.assert_file_count(".coverage.*", 0) - - out = self.run_command("coverage run -p b_or_c.py c") - assert out == 'done\n' - self.assert_exists(".coverage") - self.assert_file_count(".coverage.*", 1) - - # Combine the parallel coverage data files into .coverage, but don't - # use the data in .coverage already. - self.run_command("coverage combine") - self.assert_exists(".coverage") - - # 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 only 7 lines - # because we didn't keep the data from running b. - data = coverage.CoverageData() - data.read() - assert line_counts(data)['b_or_c.py'] == 7 - - def test_combine_parallel_data_keep(self): - self.make_b_or_c_py() - out = self.run_command("coverage run -p b_or_c.py b") - assert out == 'done\n' - self.assert_doesnt_exist(".coverage") - self.assert_file_count(".coverage.*", 1) - - out = self.run_command("coverage run -p b_or_c.py c") - assert out == 'done\n' - self.assert_doesnt_exist(".coverage") - - # After two -p runs, there should be two .coverage.machine.123 files. - self.assert_file_count(".coverage.*", 2) - - # Combine the parallel coverage data files into .coverage with the keep flag. - self.run_command("coverage combine --keep") - - # After combining, the .coverage file & the original combined file should still be there. - self.assert_exists(".coverage") - self.assert_file_count(".coverage.*", 2) - def test_append_data(self): self.make_b_or_c_py()