1""" 2figleafsections plugin for nose. 3 4Automatically records coverage info for Python tests and connects it with 5with test was being run at the time. Can be used to produce a "barcode" 6of code execution. 7""" 8 9DEFAULT_COVERAGE_FILE='.figleaf_sections' 10import pkg_resources 11 12try: 13 pkg_resources.require('figleaf>=0.6.1') 14 import figleaf 15except (ImportError, pkg_resources.DistributionNotFound): 16 figleaf = None 17 18import sys 19err = sys.stderr 20 21import nose.case 22from nose.plugins.base import Plugin 23 24import logging 25import os 26 27log = logging.getLogger(__name__) 28 29def calc_testname(test): 30 """ 31 Build a reasonably human-readable testname from each test. 32 """ 33 name = str(test) 34 if ' ' in name: 35 name = name.split(' ')[1] 36 37 return name 38 39class FigleafSections(Plugin): 40 def __init__(self): 41 Plugin.__init__(self) 42 self.testname = None 43 44 def add_options(self, parser, env=os.environ): 45 env_opt = 'NOSE_WITH_%s' % self.name.upper() 46 env_opt.replace('-', '_') 47 parser.add_option("--with-%s" % self.name, 48 action="store_true", 49 dest=self.enableOpt, 50 default=env.get(env_opt), 51 help="Enable plugin %s: %s [%s]" % 52 (self.__class__.__name__, self.help(), env_opt)) 53 54 parser.add_option("--figleaf-file", 55 action="store", 56 dest="figleaf_file", 57 default=None, 58 help="Store figleaf section coverage in this file") 59 60 def configure(self, options, config): 61 """ 62 Configure: enable plugin? And if so, where should the coverage 63 info be placed? 64 """ 65 self.conf = config 66 67 # enable? 68 if hasattr(options, self.enableOpt): 69 self.enabled = getattr(options, self.enableOpt) 70 71 ### save coverage file name, if given. 72 if options.figleaf_file: 73 self.figleaf_file = options.figleaf_file 74 else: 75 self.figleaf_file = DEFAULT_COVERAGE_FILE 76 77 if self.enabled and figleaf is None: 78 raise Exception("You must install figleaf 0.6.1 before you can use the figleafsections plugin! See http://darcs.idyll.org/~t/projects/figleaf/doc/") 79 80 def begin(self): 81 """ 82 Initialize: start recording coverage info. 83 """ 84 figleaf.start() 85 86 def finalize(self, result): 87 """ 88 Finalize: stop recording coverage info, save & exit. 89 """ 90 figleaf.stop() 91 92 fp = open(self.figleaf_file, 'w') 93 figleaf.dump_pickled_coverage(fp) 94 fp.close() 95 96 def startTest(self, test): 97 """ 98 Run at the beginning of each test, before per-test fixtures. 99 100 One weakness is that this is only run for specific kinds of 101 nose testcases. 102 """ 103 if isinstance(test, nose.case.FunctionTestCase) or \ 104 isinstance(test, nose.case.MethodTestCase): 105 self.testname = calc_testname(test) 106 assert self.testname 107 108 figleaf.start_section(self.testname) 109 110 def stopTest(self, test): 111 """ 112 Run at the end of each test, after per-test fixtures. 113 """ 114 if self.testname: 115 figleaf.stop_section() 116 self.testname = None 117 118