| import imp |
| import os |
| import sys |
| from test import test_support |
| import unittest |
| |
| import trace |
| from trace import CoverageResults, Trace |
| |
| |
| #------------------------------- Utilities -----------------------------------# |
| |
| def make_fake_module(): |
| """Creates a fake module named 'fakemodule'. |
| |
| The new module has a single function named 'foo', and it's placed in |
| sys.modules |
| The file this fake module "comes from" is fakefile.py |
| |
| """ |
| |
| # Prepare the function to import from the fake module |
| # |
| _fake_foo_src = r''' |
| def foo(a_): |
| b = a_ + 1 |
| return b + 2 |
| '''.lstrip() |
| |
| _fake_foo = compile(_fake_foo_src, 'fakefile.py', 'exec') |
| |
| # Create a new module, place the function into it and add it to sys.modules |
| # |
| fakemodule = imp.new_module('fakemodule') |
| exec _fake_foo in fakemodule.__dict__ |
| fakemodule.__file__ = 'fakefile.py' |
| sys.modules['fakemodule'] = fakemodule |
| |
| |
| def modname(filename): |
| """Infer a module name from a containing file name""" |
| base = os.path.basename(filename) |
| mod, ext = os.path.splitext(base) |
| return mod |
| |
| |
| def my_file_and_modname(): |
| """The file and module name of this file (__file__)""" |
| return __file__, modname(__file__) |
| |
| |
| #-------------------- Target functions for tracing ---------------------------# |
| |
| def _traced_func_linear(a_, b_): |
| a = a_ |
| b = b_ |
| c = a + b |
| return c |
| |
| def _traced_func_loop(a_, b_): |
| c = a_ |
| for i in range(5): |
| c += b_ |
| return c |
| |
| # Expects the 'fakemodule' module to exist and have a 'foo' function in it |
| # |
| def _traced_func_importing(a_, b_): |
| from fakemodule import foo |
| return a_ + b_ + foo(1) |
| |
| def _traced_func_simple_caller(a_): |
| c = _traced_func_linear(a_, a_) |
| return c + a_ |
| |
| def _traced_func_importing_caller(a_): |
| k = _traced_func_simple_caller(a_) |
| k += _traced_func_importing(k, a_) |
| return k |
| |
| |
| #------------------------------ Test cases -----------------------------------# |
| |
| |
| class TestLineCounts(unittest.TestCase): |
| """White-box testing of line-counting, via runfunc""" |
| def setUp(self): |
| self.tr = Trace(count=1, trace=0, countfuncs=0, countcallers=0) |
| |
| def test_traced_func_linear(self): |
| result = self.tr.runfunc(_traced_func_linear, 2, 5) |
| self.assertEqual(result, 7) |
| |
| # all lines are executed once |
| expected = {} |
| firstlineno = _traced_func_linear.__code__.co_firstlineno |
| for i in range(1, 5): |
| expected[(__file__, firstlineno + i)] = 1 |
| |
| self.assertEqual(self.tr.results().counts, expected) |
| |
| def test_traced_func_loop(self): |
| self.tr.runfunc(_traced_func_loop, 2, 3) |
| |
| firstlineno = _traced_func_loop.__code__.co_firstlineno |
| expected = { |
| (__file__, firstlineno + 1): 1, |
| (__file__, firstlineno + 2): 6, |
| (__file__, firstlineno + 3): 5, |
| (__file__, firstlineno + 4): 1, |
| } |
| self.assertEqual(self.tr.results().counts, expected) |
| |
| def test_traced_func_importing(self): |
| make_fake_module() |
| self.tr.runfunc(_traced_func_importing, 2, 5) |
| |
| firstlineno = _traced_func_importing.__code__.co_firstlineno |
| expected = { |
| (__file__, firstlineno + 1): 1, |
| (__file__, firstlineno + 2): 1, |
| ('fakefile.py', 2): 1, |
| ('fakefile.py', 3): 1, |
| } |
| self.assertEqual(self.tr.results().counts, expected) |
| |
| |
| class TestRunExecCounts(unittest.TestCase): |
| """A simple sanity test of line-counting, via run (exec)""" |
| def test_tt(self): |
| self.tr = Trace(count=1, trace=0, countfuncs=0, countcallers=0) |
| code = r'''_traced_func_loop(2, 5)''' |
| code = compile(code, __file__, 'exec') |
| self.tr.run(code) |
| |
| firstlineno = _traced_func_loop.__code__.co_firstlineno |
| expected = { |
| (__file__, firstlineno + 1): 1, |
| (__file__, firstlineno + 2): 6, |
| (__file__, firstlineno + 3): 5, |
| (__file__, firstlineno + 4): 1, |
| } |
| |
| # When used through 'run', some other spurios counts are produced, like |
| # the settrace of threading, which we ignore, just making sure that the |
| # counts fo _traced_func_loop were right. |
| # |
| for k in expected.keys(): |
| self.assertEqual(self.tr.results().counts[k], expected[k]) |
| |
| |
| class TestFuncs(unittest.TestCase): |
| """White-box testing of funcs tracing""" |
| def setUp(self): |
| self.tr = Trace(count=0, trace=0, countfuncs=1) |
| self.filemod = my_file_and_modname() |
| |
| def test_simple_caller(self): |
| self.tr.runfunc(_traced_func_simple_caller, 1) |
| |
| expected = { |
| self.filemod + ('_traced_func_simple_caller',): 1, |
| self.filemod + ('_traced_func_linear',): 1, |
| } |
| self.assertEqual(self.tr.results().calledfuncs, expected) |
| |
| def test_loop_caller_importing(self): |
| make_fake_module() |
| self.tr.runfunc(_traced_func_importing_caller, 1) |
| |
| expected = { |
| self.filemod + ('_traced_func_simple_caller',): 1, |
| self.filemod + ('_traced_func_linear',): 1, |
| self.filemod + ('_traced_func_importing_caller',): 1, |
| self.filemod + ('_traced_func_importing',): 1, |
| ('fakefile.py', 'fakefile', 'foo'): 1, |
| } |
| self.assertEqual(self.tr.results().calledfuncs, expected) |
| |
| |
| class TestCallers(unittest.TestCase): |
| """White-box testing of callers tracing""" |
| def setUp(self): |
| self.tr = Trace(count=0, trace=0, countcallers=1) |
| self.filemod = my_file_and_modname() |
| |
| def test_loop_caller_importing(self): |
| make_fake_module() |
| self.tr.runfunc(_traced_func_importing_caller, 1) |
| |
| expected = { |
| ((os.path.splitext(trace.__file__)[0] + '.py', 'trace', 'Trace.runfunc'), |
| (self.filemod + ('_traced_func_importing_caller',))): 1, |
| ((self.filemod + ('_traced_func_simple_caller',)), |
| (self.filemod + ('_traced_func_linear',))): 1, |
| ((self.filemod + ('_traced_func_importing_caller',)), |
| (self.filemod + ('_traced_func_simple_caller',))): 1, |
| ((self.filemod + ('_traced_func_importing_caller',)), |
| (self.filemod + ('_traced_func_importing',))): 1, |
| ((self.filemod + ('_traced_func_importing',)), |
| ('fakefile.py', 'fakefile', 'foo')): 1, |
| } |
| self.assertEqual(self.tr.results().callers, expected) |
| |
| |
| #------------------------------ Driver ---------------------------------------# |
| |
| def test_main(): |
| print(__name__, type(__name__)) |
| test_support.run_unittest(__name__) |
| |
| |
| if __name__ == '__main__': |
| test_main() |