diff options
Diffstat (limited to 'test/test_process.py')
-rw-r--r-- | test/test_process.py | 224 |
1 files changed, 199 insertions, 25 deletions
diff --git a/test/test_process.py b/test/test_process.py index 89804c16..2d926038 100644 --- a/test/test_process.py +++ b/test/test_process.py @@ -6,6 +6,7 @@ import coverage sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k from coveragetest import CoverageTest +here = os.path.dirname(__file__) class ProcessTest(CoverageTest): """Tests of the per-process behavior of coverage.py.""" @@ -24,9 +25,9 @@ class ProcessTest(CoverageTest): w = "world" """) - self.assertFalse(os.path.exists(".coverage")) + self.assert_doesnt_exist(".coverage") self.run_command("coverage -x mycode.py") - self.assertTrue(os.path.exists(".coverage")) + self.assert_exists(".coverage") def test_environment(self): # Checks that we can import modules from the test directory at all! @@ -37,9 +38,9 @@ class ProcessTest(CoverageTest): print ('done') """) - self.assertFalse(os.path.exists(".coverage")) + self.assert_doesnt_exist(".coverage") out = self.run_command("coverage -x mycode.py") - self.assertTrue(os.path.exists(".coverage")) + self.assert_exists(".coverage") self.assertEqual(out, 'done\n') def test_combine_parallel_data(self): @@ -56,18 +57,18 @@ class ProcessTest(CoverageTest): out = self.run_command("coverage -x -p b_or_c.py b") self.assertEqual(out, 'done\n') - self.assertFalse(os.path.exists(".coverage")) + self.assert_doesnt_exist(".coverage") out = self.run_command("coverage -x -p b_or_c.py c") self.assertEqual(out, 'done\n') - self.assertFalse(os.path.exists(".coverage")) + self.assert_doesnt_exist(".coverage") # After two -p runs, there should be two .coverage.machine.123 files. self.assertEqual(self.number_of_data_files(), 2) # Combine the parallel coverage data files into .coverage . self.run_command("coverage -c") - self.assertTrue(os.path.exists(".coverage")) + self.assert_exists(".coverage") # After combining, there should be only the .coverage file. self.assertEqual(self.number_of_data_files(), 1) @@ -97,19 +98,19 @@ class ProcessTest(CoverageTest): out = self.run_command("coverage run b_or_c.py b") self.assertEqual(out, 'done\n') - self.assertFalse(os.path.exists(".coverage")) + self.assert_doesnt_exist(".coverage") out = self.run_command("coverage run b_or_c.py c") self.assertEqual(out, 'done\n') - self.assertFalse(os.path.exists(".coverage")) + self.assert_doesnt_exist(".coverage") # After two runs, there should be two .coverage.machine.123 files. self.assertEqual(self.number_of_data_files(), 2) # Combine the parallel coverage data files into .coverage . self.run_command("coverage combine") - self.assertTrue(os.path.exists(".coverage")) - self.assertTrue(os.path.exists(".coveragerc")) + self.assert_exists(".coverage") + self.assert_exists(".coveragerc") # After combining, there should be only the .coverage file. self.assertEqual(self.number_of_data_files(), 1) @@ -128,6 +129,57 @@ class ProcessTest(CoverageTest): b_or_c 7 0 100% """)) + def test_combine_with_aliases(self): + self.make_file("d1/x.py", """\ + a = 1 + b = 2 + print("%s %s" % (a, b)) + """) + + self.make_file("d2/x.py", """\ + # 1 + # 2 + # 3 + c = 4 + d = 5 + print("%s %s" % (c, d)) + """) + + self.make_file(".coveragerc", """\ + [run] + parallel = True + + [paths] + source = + src + */d1 + */d2 + """) + + out = self.run_command("coverage run " + os.path.normpath("d1/x.py")) + self.assertEqual(out, '1 2\n') + out = self.run_command("coverage run " + os.path.normpath("d2/x.py")) + self.assertEqual(out, '4 5\n') + + self.assertEqual(self.number_of_data_files(), 2) + + self.run_command("coverage combine") + self.assert_exists(".coverage") + + # After combining, there should be only the .coverage file. + self.assertEqual(self.number_of_data_files(), 1) + + # Read the coverage data file and see that the two different x.py + # files have been combined together. + data = coverage.CoverageData() + data.read_file(".coverage") + summary = data.summary(fullpath=True) + self.assertEqual(len(summary), 1) + actual = os.path.normcase(os.path.abspath(list(summary.keys())[0])) + expected = os.path.normcase(os.path.abspath('src/x.py')) + self.assertEqual(actual, expected) + self.assertEqual(list(summary.values())[0], 6) + def test_missing_source_file(self): # Check what happens if the source is missing when reporting happens. self.make_file("fleeting.py", """\ @@ -138,7 +190,7 @@ class ProcessTest(CoverageTest): os.remove("fleeting.py") out = self.run_command("coverage html -d htmlcov") self.assertRegexpMatches(out, "No source for code: '.*fleeting.py'") - self.assertFalse("Traceback" in out) + self.assertNotIn("Traceback", out) # It happens that the code paths are different for *.py and other # files, so try again with no extension. @@ -150,13 +202,13 @@ class ProcessTest(CoverageTest): os.remove("fleeting") status, out = self.run_command_status("coverage html -d htmlcov", 1) self.assertRegexpMatches(out, "No source for code: '.*fleeting'") - self.assertFalse("Traceback" in out) + self.assertNotIn("Traceback", out) self.assertEqual(status, 1) def test_running_missing_file(self): status, out = self.run_command_status("coverage run xyzzy.py", 1) self.assertRegexpMatches(out, "No file to run: .*xyzzy.py") - self.assertFalse("Traceback" in out) + self.assertNotIn("Traceback", out) self.assertEqual(status, 1) def test_code_throws(self): @@ -174,12 +226,16 @@ class ProcessTest(CoverageTest): # same traceback. status, out = self.run_command_status("coverage run throw.py", 1) out2 = self.run_command("python throw.py") + if '__pypy__' in sys.builtin_module_names: + # Pypy has an extra frame in the traceback for some reason + lines2 = out2.splitlines() + out2 = "".join([l+"\n" for l in lines2 if "toplevel" not in l]) self.assertMultiLineEqual(out, out2) # But also make sure that the output is what we expect. - self.assertTrue('File "throw.py", line 5, in f2' in out) - self.assertTrue('raise Exception("hey!")' in out) - self.assertFalse('coverage' in out) + 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 test_code_exits(self): @@ -220,6 +276,28 @@ class ProcessTest(CoverageTest): self.assertEqual(status, status2) self.assertEqual(status, 0) + def test_coverage_run_is_like_python(self): + tryfile = os.path.join(here, "try_execfile.py") + self.make_file("run_me.py", open(tryfile).read()) + out = self.run_command("coverage run run_me.py") + out2 = self.run_command("python run_me.py") + self.assertMultiLineEqual(out, out2) + + if sys.version_info >= (2, 6): # Doesn't work in 2.5, and I don't care! + def test_coverage_run_dashm_is_like_python_dashm(self): + # These -m commands assume the coverage tree is on the path. + out = self.run_command("coverage run -m test.try_execfile") + out2 = self.run_command("python -m test.try_execfile") + self.assertMultiLineEqual(out, out2) + + if 0: + # For https://bitbucket.org/ned/coveragepy/issue/207 + def test_coverage_run_dashm_is_like_python_dashm_with__main__(self): + self.make_file("package/__init__.py") # empty + self.make_file("package/__main__.py", "#\n") # empty + out = self.run_command("coverage run -m package") + out2 = self.run_command("python -m package") + self.assertMultiLineEqual(out, out2) if hasattr(os, 'fork'): def test_fork(self): @@ -242,7 +320,7 @@ class ProcessTest(CoverageTest): out = self.run_command("coverage run -p fork.py") self.assertEqual(out, 'Child!\n') - self.assertFalse(os.path.exists(".coverage")) + self.assert_doesnt_exist(".coverage") # After running the forking program, there should be two # .coverage.machine.123 files. @@ -250,7 +328,7 @@ class ProcessTest(CoverageTest): # Combine the parallel coverage data files into .coverage . self.run_command("coverage -c") - self.assertTrue(os.path.exists(".coverage")) + self.assert_exists(".coverage") # After combining, there should be only the .coverage file. self.assertEqual(self.number_of_data_files(), 1) @@ -268,10 +346,106 @@ class ProcessTest(CoverageTest): """) out = self.run_command("coverage run --source=sys,xyzzy,quux hello.py") - self.assertTrue("Hello\n" in out) - self.assertTrue(textwrap.dedent("""\ - Coverage.py warning: Module sys has no python source. - Coverage.py warning: Source module xyzzy was never encountered. - Coverage.py warning: Source module quux was never encountered. + self.assertIn("Hello\n", out) + self.assertIn(textwrap.dedent("""\ + Coverage.py warning: Module sys has no Python source. + Coverage.py warning: Module xyzzy was never imported. + Coverage.py warning: Module quux was never imported. Coverage.py warning: No data was collected. - """) in out) + """), out) + + def test_warnings_if_never_run(self): + out = self.run_command("coverage run i_dont_exist.py") + self.assertIn("No file to run: 'i_dont_exist.py'", out) + self.assertNotIn("warning", out) + self.assertNotIn("Exception", out) + + out = self.run_command("coverage run -m no_such_module") + self.assertTrue( + ("No module named no_such_module" in out) or + ("No module named 'no_such_module'" in out) + ) + self.assertNotIn("warning", out) + self.assertNotIn("Exception", out) + + if sys.version_info >= (3, 0): # This only works on 3.x for now. + # It only works with the C tracer. + if os.getenv('COVERAGE_TEST_TRACER', 'c') == 'c': + 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 -m coverage run -L getenv.py") + self.assertEqual(out, "FOOEY == BOO\n") + data = coverage.CoverageData() + data.read_file(".coverage") + # The actual number of executed lines in os.py when it's + # imported is 120 or so. Just running os.getenv executes + # about 5. + self.assertGreater(data.summary()['os.py'], 50) + + +class AliasedCommandTests(CoverageTest): + """Tests of the version-specific command aliases.""" + + def test__major_version_works(self): + # "coverage2" works on py2 + cmd = "coverage%d" % sys.version_info[0] + out = self.run_command(cmd) + self.assertIn("Code coverage for Python", out) + + def test_wrong_alias_doesnt_work(self): + # "coverage3" doesn't work on py2 + badcmd = "coverage%d" % (5 - sys.version_info[0]) + out = self.run_command(badcmd) + self.assertNotIn("Code coverage for Python", out) + + def test_specific_alias_works(self): + # "coverage-2.7" works on py2.7 + cmd = "coverage-%d.%d" % sys.version_info[:2] + out = self.run_command(cmd) + self.assertIn("Code coverage for Python", out) + + +class FailUnderTest(CoverageTest): + """Tests of the --fail-under switch.""" + + def setUp(self): + super(FailUnderTest, self).setUp() + self.make_file("fifty.py", """\ + # I have 50% coverage! + a = 1 + if a > 2: + b = 3 + c = 4 + """) + st, _ = self.run_command_status("coverage run fifty.py", 0) + self.assertEqual(st, 0) + + def test_report(self): + st, _ = self.run_command_status("coverage report --fail-under=50", 0) + self.assertEqual(st, 0) + st, _ = self.run_command_status("coverage report --fail-under=51", 2) + self.assertEqual(st, 2) + + def test_html_report(self): + st, _ = self.run_command_status("coverage html --fail-under=50", 0) + self.assertEqual(st, 0) + st, _ = self.run_command_status("coverage html --fail-under=51", 2) + self.assertEqual(st, 2) + + def test_xml_report(self): + st, _ = self.run_command_status("coverage xml --fail-under=50", 0) + self.assertEqual(st, 0) + st, _ = self.run_command_status("coverage xml --fail-under=51", 2) + self.assertEqual(st, 2) |