From a3cb81edd6053a273447ba3821655320ed234a41 Mon Sep 17 00:00:00 2001 From: buck Date: Wed, 15 Oct 2014 12:04:05 -0700 Subject: make --source and -m play nice together --HG-- branch : __main__-support extra : rebase_source : c9ca9fddecafddd5ef4db9cc64ca1c0972130aab --- tests/test_cmdline.py | 9 +++++--- tests/test_files.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++- tests/test_process.py | 49 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index 695c3bec..3032a2f1 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -33,6 +33,9 @@ class BaseCmdLineTest(CoverageTest): ignore_errors=None, include=None, omit=None, morfs=[], show_missing=None, ) + defaults.start( + main_module=None, + ) defaults.xml_report( ignore_errors=None, include=None, omit=None, morfs=[], outfile=None, ) @@ -472,7 +475,7 @@ class CmdLineTest(BaseCmdLineTest): self.cmd_executes("run -m mymodule", """\ .coverage() .erase() - .start() + .start(main_module='mymodule') .run_python_module('mymodule', ['mymodule']) .stop() .save() @@ -480,7 +483,7 @@ class CmdLineTest(BaseCmdLineTest): self.cmd_executes("run -m mymodule -qq arg1 arg2", """\ .coverage() .erase() - .start() + .start(main_module='mymodule') .run_python_module('mymodule', ['mymodule', '-qq', 'arg1', 'arg2']) .stop() .save() @@ -488,7 +491,7 @@ class CmdLineTest(BaseCmdLineTest): self.cmd_executes("run --branch -m mymodule", """\ .coverage(branch=True) .erase() - .start() + .start(main_module='mymodule') .run_python_module('mymodule', ['mymodule']) .stop() .save() diff --git a/tests/test_files.py b/tests/test_files.py index 648c76a9..d72788c4 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -2,7 +2,9 @@ import os, os.path -from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher +from coverage.files import ( + FileLocator, TreeMatcher, FnmatchMatcher, ModuleMatcher +) from coverage.files import PathAliases, find_python_files, abs_file from coverage.misc import CoverageException @@ -80,6 +82,64 @@ class MatcherTest(CoverageTest): for filepath, matches in matches_to_try: self.assertMatches(tm, filepath, matches) + def test_module_matcher(self): + matches_to_try = [ + ('test', True), + ('test', True), + ('trash', False), + ('testing', False), + ('test.x', True), + ('test.x.y.z', True), + ('py', False), + ('py.t', False), + ('py.test', True), + ('py.testing', False), + ('py.test.buz', True), + ('py.test.buz.baz', True), + ('__main__', False), + ('mymain', True), + ('yourmain', False), + ] + modules = ['test', 'py.test', 'mymain'] + for mm in ( + ModuleMatcher(modules), + ModuleMatcher(modules, main_module=None), + ModuleMatcher(modules, main_module='yourmain'), + ): + self.assertEqual( + mm.info(), + ['main_module=%r' % mm.main_module] + modules + ) + for modulename, matches in matches_to_try: + self.assertEqual( + mm.match(modulename), + modulename if matches else False, + modulename, + ) + + def test_module_matcher_dunder_main(self): + matches_to_try = [ + ('__main__', True), + ('mymain', True), + ('yourmain', False), + ] + modules = ['test', 'py.test', 'mymain'] + mm = ModuleMatcher(modules, main_module='mymain') + self.assertEqual(mm.info(), ["main_module='mymain'"] + modules) + for modulename, matches in matches_to_try: + if not matches: + expected = False + elif modulename == '__main__': + expected = mm.main_module + else: + expected = modulename + + self.assertEqual( + mm.match(modulename), + expected, + modulename, + ) + def test_fnmatch_matcher(self): matches_to_try = [ (self.make_file("sub/file1.py"), True), diff --git a/tests/test_process.py b/tests/test_process.py index ac5c6e1b..e53e64c9 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -331,6 +331,55 @@ class ProcessTest(CoverageTest): out_py = self.run_command("python -m tests.try_execfile") self.assertMultiLineEqual(out_cov, out_py) + def test_coverage_run_dashm_equal_to_doubledashsource(self): + """regression test for #328 + + When imported by -m, a module's __name__ is __main__, but we need the + --source machinery to know and respect the original name. + """ + # These -m commands assume the coverage tree is on the path. + out_cov = self.run_command( + "coverage run --source tests.try_execfile -m tests.try_execfile" + ) + out_py = self.run_command("python -m tests.try_execfile") + self.assertMultiLineEqual(out_cov, out_py) + + def test_coverage_run_dashm_superset_of_doubledashsource(self): + """Edge case: --source foo -m foo.bar""" + # These -m commands assume the coverage tree is on the path. + out_cov = self.run_command( + "coverage run --source tests -m tests.try_execfile" + ) + out_py = self.run_command("python -m tests.try_execfile") + self.assertMultiLineEqual(out_cov, out_py) + + st, out = self.run_command_status("coverage report") + self.assertEqual(st, 0) + self.assertEqual(self.line_count(out), 6, out) + + def test_coverage_run_script_imports_doubledashsource(self): + self.make_file("myscript", """\ + import sys + sys.dont_write_bytecode = True + + def main(): + import tests.try_execfile + + if __name__ == '__main__': + main() + """) + + # These -m commands assume the coverage tree is on the path. + out_cov = self.run_command( + "coverage run --source tests myscript" + ) + out_py = self.run_command("python myscript") + self.assertMultiLineEqual(out_cov, out_py) + + st, out = self.run_command_status("coverage report") + self.assertEqual(st, 0) + self.assertEqual(self.line_count(out), 6, out) + def test_coverage_run_dashm_is_like_python_dashm_off_path(self): # https://bitbucket.org/ned/coveragepy/issue/242 tryfile = os.path.join(here, "try_execfile.py") -- cgit v1.2.1 From d05360a060187452f49302467f87ead09d27c9ba Mon Sep 17 00:00:00 2001 From: Buck Golemon Date: Fri, 14 Nov 2014 14:00:27 -0800 Subject: ModuleFinder no longer takes a main-module argument. --HG-- branch : __main__-support extra : rebase_source : 3f4c29876960153907b65b6e8e818b8228ca4ec0 extra : histedit_source : 6567adaf9c89483b71501fd91e9d3c83ed3daec7%2C2c5c8a7af95b8b26af384b9a65815d077e4313ec --- tests/test_cmdline.py | 9 +++------ tests/test_files.py | 39 ++++++--------------------------------- 2 files changed, 9 insertions(+), 39 deletions(-) (limited to 'tests') diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index 3032a2f1..695c3bec 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -33,9 +33,6 @@ class BaseCmdLineTest(CoverageTest): ignore_errors=None, include=None, omit=None, morfs=[], show_missing=None, ) - defaults.start( - main_module=None, - ) defaults.xml_report( ignore_errors=None, include=None, omit=None, morfs=[], outfile=None, ) @@ -475,7 +472,7 @@ class CmdLineTest(BaseCmdLineTest): self.cmd_executes("run -m mymodule", """\ .coverage() .erase() - .start(main_module='mymodule') + .start() .run_python_module('mymodule', ['mymodule']) .stop() .save() @@ -483,7 +480,7 @@ class CmdLineTest(BaseCmdLineTest): self.cmd_executes("run -m mymodule -qq arg1 arg2", """\ .coverage() .erase() - .start(main_module='mymodule') + .start() .run_python_module('mymodule', ['mymodule', '-qq', 'arg1', 'arg2']) .stop() .save() @@ -491,7 +488,7 @@ class CmdLineTest(BaseCmdLineTest): self.cmd_executes("run --branch -m mymodule", """\ .coverage(branch=True) .erase() - .start(main_module='mymodule') + .start() .run_python_module('mymodule', ['mymodule']) .stop() .save() diff --git a/tests/test_files.py b/tests/test_files.py index d72788c4..f6976a81 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -101,42 +101,15 @@ class MatcherTest(CoverageTest): ('yourmain', False), ] modules = ['test', 'py.test', 'mymain'] - for mm in ( - ModuleMatcher(modules), - ModuleMatcher(modules, main_module=None), - ModuleMatcher(modules, main_module='yourmain'), - ): - self.assertEqual( - mm.info(), - ['main_module=%r' % mm.main_module] + modules - ) - for modulename, matches in matches_to_try: - self.assertEqual( - mm.match(modulename), - modulename if matches else False, - modulename, - ) - - def test_module_matcher_dunder_main(self): - matches_to_try = [ - ('__main__', True), - ('mymain', True), - ('yourmain', False), - ] - modules = ['test', 'py.test', 'mymain'] - mm = ModuleMatcher(modules, main_module='mymain') - self.assertEqual(mm.info(), ["main_module='mymain'"] + modules) + mm = ModuleMatcher(modules) + self.assertEqual( + mm.info(), + modules + ) for modulename, matches in matches_to_try: - if not matches: - expected = False - elif modulename == '__main__': - expected = mm.main_module - else: - expected = modulename - self.assertEqual( mm.match(modulename), - expected, + matches, modulename, ) -- cgit v1.2.1 From 7ca11054c5b0f91bd77c16923ec443ccee6f2dd9 Mon Sep 17 00:00:00 2001 From: Buck Golemon Date: Fri, 14 Nov 2014 14:00:48 -0800 Subject: shim for pep302 __loader__ --HG-- branch : __main__-support extra : histedit_source : f07b26f0cfc575d81972546f1b7ae2ece84e2d87 --- tests/try_execfile.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests') diff --git a/tests/try_execfile.py b/tests/try_execfile.py index 314ffae0..fd430e6b 100644 --- a/tests/try_execfile.py +++ b/tests/try_execfile.py @@ -60,6 +60,8 @@ globals_to_check = { '__doc__': __doc__, '__builtins__.has_open': hasattr(__builtins__, 'open'), '__builtins__.dir': dir(__builtins__), + '__loader__ exists': '__loader__' in globals(), + '__loader__.fullname': getattr(globals().get('__loader__', None), 'fullname', None), '__package__': __package__, 'DATA': DATA, 'FN_VAL': FN_VAL, -- cgit v1.2.1 From 148a2291e1e7b04eecaa15c90b125cc8199d7974 Mon Sep 17 00:00:00 2001 From: Buck Golemon Date: Fri, 14 Nov 2014 16:33:41 -0800 Subject: they changed the way __loader__ looks in 3.3 --HG-- branch : __main__-support extra : amend_source : 7abd8465667b4bd4b3eeac24391c27c68edf9a95 --- tests/try_execfile.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/try_execfile.py b/tests/try_execfile.py index fd430e6b..ee5bae5c 100644 --- a/tests/try_execfile.py +++ b/tests/try_execfile.py @@ -54,14 +54,17 @@ def my_function(a): FN_VAL = my_function("fooey") +loader = globals().get('__loader__') +fullname = getattr(loader, 'fullname', None) or getattr(loader, 'name', None) + globals_to_check = { '__name__': __name__, '__file__': __file__, '__doc__': __doc__, '__builtins__.has_open': hasattr(__builtins__, 'open'), '__builtins__.dir': dir(__builtins__), - '__loader__ exists': '__loader__' in globals(), - '__loader__.fullname': getattr(globals().get('__loader__', None), 'fullname', None), + '__loader__ exists': loader is not None, + '__loader__.fullname': fullname, '__package__': __package__, 'DATA': DATA, 'FN_VAL': FN_VAL, -- cgit v1.2.1 From b3ccb75241566c1e1a814ae99a84637fd0ac2b44 Mon Sep 17 00:00:00 2001 From: Buck Golemon Date: Sat, 15 Nov 2014 14:01:06 -0800 Subject: add necessary tests, fix attrname, once it was shown to fail --HG-- branch : __main__-support --- tests/test_process.py | 102 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/test_process.py b/tests/test_process.py index e53e64c9..df26aaf5 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -662,11 +662,10 @@ class FailUnderTest(CoverageTest): self.assertEqual(st, 2) -class ProcessStartupTest(CoverageTest): - """Test that we can measure coverage in subprocesses.""" - +class ProcessCoverageMixin(object): + """Set up a .pth file that causes all subprocesses to be coverage'd""" def setUp(self): - super(ProcessStartupTest, self).setUp() + super(ProcessCoverageMixin, self).setUp() # Find a place to put a .pth file. pth_contents = "import coverage; coverage.process_startup()\n" for d in sys.path: # pragma: part covered @@ -684,10 +683,14 @@ class ProcessStartupTest(CoverageTest): raise Exception("Couldn't find a place for the .pth file") def tearDown(self): - super(ProcessStartupTest, self).tearDown() + super(ProcessCoverageMixin, self).tearDown() # Clean up the .pth file we made. os.remove(self.pth_path) + +class ProcessStartupTest(ProcessCoverageMixin, CoverageTest): + """Test that we can measure coverage in subprocesses.""" + def test_subprocess_with_pth_files(self): # pragma: not covered if os.environ.get('COVERAGE_COVERAGE', ''): raise SkipTest( @@ -720,3 +723,92 @@ class ProcessStartupTest(CoverageTest): data = coverage.CoverageData() data.read_file(".mycovdata") self.assertEqual(data.summary()['sub.py'], 2) + + +class ProcessStartupWithSourceTest(ProcessCoverageMixin, CoverageTest): + """Show that we can configure {[run]source} during process-level coverage. + + There are two interesting variables: + 1) -m versus a simple script argument (eg `python myscript`) + 2) filtering for the top-level (main.py) or second-level (sub.py) module + 3) whether the files are in a package or not + + ... for a total of eight tests. + """ + def assert_pth_and_source_work_together(self, dashm, package, source): + def fullname(modname): + if package and dashm: + return '.'.join((package, modname)) + else: + return modname + + def path(basename): + return os.path.join(package, basename) + + if os.environ.get('COVERAGE_COVERAGE', ''): + raise SkipTest( + "Can't test subprocess pth file suppport during metacoverage" + ) + # Main will run sub.py + self.make_file(path("main.py"), """\ + import %s + if True: pass + """ % fullname('sub')) + if package: + self.make_file(path("__init__.py"), '') + # sub.py will write a few lines. + self.make_file(path("sub.py"), """\ + with open("out.txt", "w") as f: + f.write("Hello, world!\\n") + """) + self.make_file("coverage.ini", """\ + [run] + source = %s + """ % fullname(source) + ) + + self.set_environ("COVERAGE_PROCESS_START", "coverage.ini") + + if dashm: + cmd = (sys.executable, dashm, fullname('main')) + else: + cmd = (sys.executable, path('main.py')) + + from subprocess import Popen + Popen(cmd).wait() + + with open("out.txt") as f: + self.assertEqual(f.read(), "Hello, world!\n") + + # Read the data from .coverage + self.assert_exists(".coverage") + data = coverage.CoverageData() + data.read_file(".coverage") + summary = data.summary() + print(summary) + self.assertEqual(summary[source + '.py'], 2) + self.assertEqual(len(summary), 1) + + def test_dashm_main(self): + self.assert_pth_and_source_work_together('-m', '', 'main') + + def test_script_main(self): + self.assert_pth_and_source_work_together('', '', 'main') + + def test_dashm_sub(self): + self.assert_pth_and_source_work_together('-m', '', 'sub') + + def test_script_sub(self): + self.assert_pth_and_source_work_together('', '', 'sub') + + def test_dashm_pkg_main(self): + self.assert_pth_and_source_work_together('-m', 'pkg', 'main') + + def test_script_pkg_main(self): + self.assert_pth_and_source_work_together('', 'pkg', 'main') + + def test_dashm_pkg_sub(self): + self.assert_pth_and_source_work_together('-m', 'pkg', 'sub') + + def test_script_pkg_sub(self): + self.assert_pth_and_source_work_together('', 'pkg', 'sub') -- cgit v1.2.1