annotate bitten/util/testrunner.py @ 868:242f2e225c4e 0.6.x

0.6dev: Merged [928,935:937,943:945] from trunk.
author hodgestar
date Mon, 18 Oct 2010 11:52:18 +0000
parents f4d07544722b
children
rev   line source
379
0df178e07fdb Use UTF-8 as encoding of source files.
cmlenz
parents: 367
diff changeset
1 # -*- coding: utf-8 -*-
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
2 #
408
933105ab516b Update file headers and other stuff pointing to the old home.
cmlenz
parents: 379
diff changeset
3 # Copyright (C) 2005-2007 Christopher Lenz <cmlenz@gmx.de>
482
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
4 # Copyright (C) 2008 Matt Good <matt@matt-good.net>
833
f4d07544722b 0.6dev: Merged [910] from trunk.
osimons
parents: 512
diff changeset
5 # Copyright (C) 2008-2010 Edgewall Software
163
634be6cbb808 Flip the switch: Bitten is now BSD-licensed.
cmlenz
parents: 144
diff changeset
6 # All rights reserved.
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
7 #
163
634be6cbb808 Flip the switch: Bitten is now BSD-licensed.
cmlenz
parents: 144
diff changeset
8 # This software is licensed as described in the file COPYING, which
634be6cbb808 Flip the switch: Bitten is now BSD-licensed.
cmlenz
parents: 144
diff changeset
9 # you should have received as part of this distribution. The terms
408
933105ab516b Update file headers and other stuff pointing to the old home.
cmlenz
parents: 379
diff changeset
10 # are also available at http://bitten.edgewall.org/wiki/License.
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
11
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
12 from distutils import log
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
13 from distutils.errors import DistutilsOptionError
60
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
14 import os
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
15 import re
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
16 from StringIO import StringIO
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
17 import sys
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
18 import time
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
19 from pkg_resources import Distribution, EntryPoint, PathMetadata, \
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
20 normalize_path, require, working_set
356
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
21 from setuptools.command.test import test
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
22 from unittest import _TextTestResult, TextTestRunner
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
23
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
24 from bitten import __version__ as VERSION
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
25 from bitten.util import xmlio
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
26
411
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
27 __docformat__ = 'restructuredtext en'
a169d2e96463 Use reStructuredText as the API documentation syntax.
cmlenz
parents: 408
diff changeset
28
60
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
29
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
30 class XMLTestResult(_TextTestResult):
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
31
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
32 def __init__(self, stream, descriptions, verbosity):
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
33 _TextTestResult.__init__(self, stream, descriptions, verbosity)
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
34 self.tests = []
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
35
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
36 def startTest(self, test):
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
37 _TextTestResult.startTest(self, test)
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
38 filename = sys.modules[test.__module__].__file__
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
39 if filename.endswith('.pyc') or filename.endswith('.pyo'):
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
40 filename = filename[:-1]
60
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
41 self.tests.append([test, filename, time.time(), None, None])
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
42
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
43 def stopTest(self, test):
60
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
44 self.tests[-1][2] = time.time() - self.tests[-1][2]
121
381233a91db6 Fix for the {{{unittest}}} command, which was raising an exception but swallowing the traceback.
cmlenz
parents: 105
diff changeset
45 _TextTestResult.stopTest(self, test)
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
46
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
47
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
48 class XMLTestRunner(TextTestRunner):
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
49
105
de5b6e69fc7e * Make the {{{unittest}}} command raise an exception if the tests failed, so that distutils exits with a non-zero return code.
cmlenz
parents: 60
diff changeset
50 def __init__(self, stream=sys.stdout, xml_stream=None):
de5b6e69fc7e * Make the {{{unittest}}} command raise an exception if the tests failed, so that distutils exits with a non-zero return code.
cmlenz
parents: 60
diff changeset
51 TextTestRunner.__init__(self, stream, descriptions=0, verbosity=2)
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
52 self.xml_stream = xml_stream
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
53
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
54 def _makeResult(self):
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
55 return XMLTestResult(self.stream, self.descriptions, self.verbosity)
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
56
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
57 def run(self, test):
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
58 result = TextTestRunner.run(self, test)
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
59 if not self.xml_stream:
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
60 return result
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
61
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
62 root = xmlio.Element('unittest-results')
60
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
63 for testcase, filename, timetaken, stdout, stderr in result.tests:
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
64 status = 'success'
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
65 tb = None
60
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
66
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
67 if testcase in [e[0] for e in result.errors]:
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
68 status = 'error'
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
69 tb = [e[1] for e in result.errors if e[0] is testcase][0]
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
70 elif testcase in [f[0] for f in result.failures]:
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
71 status = 'failure'
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
72 tb = [f[1] for f in result.failures if f[0] is testcase][0]
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
73
144
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
74 name = str(testcase)
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
75 fixture = None
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
76 description = testcase.shortDescription() or ''
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
77 if description.startswith('doctest of '):
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
78 name = 'doctest'
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
79 fixture = description[11:]
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
80 description = None
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
81 else:
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
82 match = re.match('(\w+)\s+\(([\w.]+)\)', name)
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
83 if match:
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
84 name = match.group(1)
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
85 fixture = match.group(2)
76dea27af878 * Make the `<python:unittest>` command strip the base dir from file names in the report. Fixes #42.
cmlenz
parents: 121
diff changeset
86
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
87 test_elem = xmlio.Element('test', file=filename, name=name,
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
88 fixture=fixture, status=status,
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
89 duration=timetaken)
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
90 if description:
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
91 test_elem.append(xmlio.Element('description')[description])
60
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
92 if stdout:
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
93 test_elem.append(xmlio.Element('stdout')[stdout])
60
055a6c666fa8 * Pass a {{{Context}}} object to recipe commands as the first argument. Currently this only has the basedir, but will be extended to also provide output recording etc.
cmlenz
parents: 22
diff changeset
94 if stderr:
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
95 test_elem.append(xmlio.Element('stdout')[stderr])
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
96 if tb:
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
97 test_elem.append(xmlio.Element('traceback')[tb])
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
98 root.append(test_elem)
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
99
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
100 root.write(self.xml_stream, newlines=True)
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
101 return result
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
102
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
103
356
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
104 class unittest(test):
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
105 description = test.description + ', and optionally record code coverage'
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
106
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
107 user_options = test.user_options + [
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
108 ('xml-output=', None,
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
109 "Path to the XML file where test results are written to"),
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
110 ('coverage-dir=', None,
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
111 "Directory where coverage files are to be stored"),
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
112 ('coverage-summary=', None,
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
113 "Path to the file where the coverage summary should be stored"),
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
114 ('coverage-method=', None,
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
115 "Whether to use trace.py or coverage.py to collect code coverage. "
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
116 "Valid options are 'trace' (the default) or 'coverage'.")
356
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
117 ]
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
118
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
119 def initialize_options(self):
356
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
120 test.initialize_options(self)
367
023b0b4a1f20 Fix options handling in `unittest` command.
cmlenz
parents: 356
diff changeset
121 self.xml_output = None
023b0b4a1f20 Fix options handling in `unittest` command.
cmlenz
parents: 356
diff changeset
122 self.xml_output_file = None
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
123 self.coverage_summary = None
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
124 self.coverage_dir = None
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
125 self.coverage_method = 'trace'
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
126
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
127 def finalize_options(self):
356
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
128 test.finalize_options(self)
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
129
367
023b0b4a1f20 Fix options handling in `unittest` command.
cmlenz
parents: 356
diff changeset
130 if self.xml_output is not None:
503
a7c795920c4a Merging trac-0.11 branch to trunk. This revision is equivalent to [571].
wbell
parents: 482
diff changeset
131 output_dir = os.path.dirname(self.xml_output) or '.'
a7c795920c4a Merging trac-0.11 branch to trunk. This revision is equivalent to [571].
wbell
parents: 482
diff changeset
132 if not os.path.exists(output_dir):
a7c795920c4a Merging trac-0.11 branch to trunk. This revision is equivalent to [571].
wbell
parents: 482
diff changeset
133 os.makedirs(output_dir)
367
023b0b4a1f20 Fix options handling in `unittest` command.
cmlenz
parents: 356
diff changeset
134 self.xml_output_file = open(self.xml_output, 'w')
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
135
482
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
136 if self.coverage_method not in ('trace', 'coverage', 'figleaf'):
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
137 raise DistutilsOptionError('Unknown coverage method %r' %
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
138 self.coverage_method)
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
139
356
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
140 def run_tests(self):
441
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
141 if self.coverage_summary:
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
142 if self.coverage_method == 'coverage':
441
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
143 self._run_with_coverage()
482
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
144 elif self.coverage_method == 'figleaf':
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
145 self._run_with_figleaf()
429
d6e1a05f32f7 Start webadmin integration.
cmlenz
parents: 411
diff changeset
146 else:
441
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
147 self._run_with_trace()
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
148 else:
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
149 self._run_tests()
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
150
482
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
151 def _run_with_figleaf(self):
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
152 import figleaf
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
153 figleaf.start()
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
154 try:
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
155 self._run_tests()
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
156 finally:
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
157 figleaf.stop()
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
158 figleaf.write_coverage(self.coverage_summary)
b87eda443ffc add figleaf coverage support
mgood
parents: 471
diff changeset
159
441
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
160 def _run_with_coverage(self):
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
161 import coverage
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
162 coverage.use_cache(False)
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
163 coverage.start()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
164 try:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
165 self._run_tests()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
166 finally:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
167 coverage.stop()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
168
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
169 modules = [m for _, m in sys.modules.items()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
170 if m is not None and hasattr(m, '__file__')
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
171 and os.path.splitext(m.__file__)[-1] in ('.py', '.pyc')]
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
172
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
173 # Generate summary file
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
174 buf = StringIO()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
175 coverage.report(modules, file=buf)
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
176 buf.seek(0)
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
177 fileobj = open(self.coverage_summary, 'w')
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
178 try:
471
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
179 filter_coverage(buf, fileobj)
441
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
180 finally:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
181 fileobj.close()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
182
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
183 if self.coverage_dir:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
184 if not os.path.exists(self.coverage_dir):
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
185 os.makedirs(self.coverage_dir)
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
186 coverage.annotate(modules, directory=self.coverage_dir,
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
187 ignore_errors=True)
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
188
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
189 def _run_with_trace(self):
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
190 from trace import Trace
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
191 trace = Trace(ignoredirs=[sys.prefix, sys.exec_prefix], trace=False,
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
192 count=True)
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
193 try:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
194 trace.runfunc(self._run_tests)
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
195 finally:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
196 results = trace.results()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
197 real_stdout = sys.stdout
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
198 sys.stdout = open(self.coverage_summary, 'w')
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
199 try:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
200 results.write_results(show_missing=True, summary=True,
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
201 coverdir=self.coverage_dir)
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
202 finally:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
203 sys.stdout.close()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
204 sys.stdout = real_stdout
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
205
22
e67713b7936f Moved test runner into {{{bitten.util}}}} package.
cmlenz
parents:
diff changeset
206 def _run_tests(self):
356
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
207 old_path = sys.path[:]
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
208 ei_cmd = self.get_finalized_command("egg_info")
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
209 path_item = normalize_path(ei_cmd.egg_base)
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
210 metadata = PathMetadata(
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
211 path_item, normalize_path(ei_cmd.egg_info)
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
212 )
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
213 dist = Distribution(path_item, metadata, project_name=ei_cmd.egg_name)
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
214 working_set.add(dist)
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
215 require(str(dist.as_requirement()))
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
216 loader_ep = EntryPoint.parse("x=" + self.test_loader)
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
217 loader_class = loader_ep.load(require=False)
173f0c362fe1 The `unittest` command is now based on the setuptools `test command.
cmlenz
parents: 295
diff changeset
218
441
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
219 try:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
220 import unittest
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
221 unittest.main(
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
222 None, None, [unittest.__file__] + self.test_args,
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
223 testRunner=XMLTestRunner(stream=sys.stdout,
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
224 xml_stream=self.xml_output_file),
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
225 testLoader=loader_class()
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
226 )
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
227 except SystemExit, e:
641a73f078f5 Experimental support for using [http://nedbatchelder.com/code/modules/coverage.html coverage.py] with the Bitten `unittest` command.
cmlenz
parents: 429
diff changeset
228 return e.code
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
229
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
230
471
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
231 def filter_coverage(infile, outfile):
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
232 for idx, line in enumerate(infile):
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
233 if idx < 2 or line.startswith('--'):
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
234 outfile.write(line)
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
235 continue
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
236 parts = line.split()
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
237 name = parts[0]
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
238 if name == 'TOTAL':
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
239 continue
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
240 if name not in sys.modules:
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
241 outfile.write(line)
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
242 continue
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
243 filename = os.path.normpath(sys.modules[name].__file__)
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
244 if filename.endswith('.pyc') or filename.endswith('.pyo'):
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
245 filename = filename[:-1]
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
246 outfile.write(line.rstrip() + ' ' + filename + '\n')
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
247
b15e6eec8422 extract the code for filtering coverage files so it can be reused
mgood
parents: 442
diff changeset
248
295
5f84af72d17f * Store executable bit in ZIP archives (from `svn:executable`).
cmlenz
parents: 221
diff changeset
249 def main():
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
250 from distutils.dist import Distribution
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
251 from optparse import OptionParser
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
252
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
253 parser = OptionParser(usage='usage: %prog [options] test_suite ...',
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
254 version='%%prog %s' % VERSION)
367
023b0b4a1f20 Fix options handling in `unittest` command.
cmlenz
parents: 356
diff changeset
255 parser.add_option('-o', '--xml-output', action='store', dest='xml_output',
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
256 metavar='FILE', help='write XML test results to FILE')
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
257 parser.add_option('-d', '--coverage-dir', action='store',
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
258 dest='coverage_dir', metavar='DIR',
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
259 help='store coverage results in DIR')
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
260 parser.add_option('-s', '--coverage-summary', action='store',
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
261 dest='coverage_summary', metavar='FILE',
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
262 help='write coverage summary to FILE')
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
263 options, args = parser.parse_args()
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
264 if len(args) < 1:
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
265 parser.error('incorrect number of arguments')
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
266
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
267 cmd = unittest(Distribution())
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
268 cmd.initialize_options()
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
269 cmd.test_suite = args[0]
367
023b0b4a1f20 Fix options handling in `unittest` command.
cmlenz
parents: 356
diff changeset
270 if hasattr(options, 'xml_output'):
023b0b4a1f20 Fix options handling in `unittest` command.
cmlenz
parents: 356
diff changeset
271 cmd.xml_output = options.xml_output
221
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
272 if hasattr(options, 'coverage_summary'):
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
273 cmd.coverage_summary = options.coverage_summary
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
274 if hasattr(options, 'coverage_dir'):
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
275 cmd.coverage_dir = options.coverage_dir
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
276 cmd.finalize_options()
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
277 cmd.run()
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
278
17e4b8d01db6 * Get rid of `xmlio.SubElement`.
cmlenz
parents: 208
diff changeset
279 if __name__ == '__main__':
512
a68da2b81220 `sys.argv` is assumed by `main`, and it takes no parameters, so removing
dfraser
parents: 503
diff changeset
280 main()
Copyright (C) 2012-2017 Edgewall Software