OLD | NEW |
1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
3 # | 3 # |
4 # This file is part of logilab-common. | 4 # This file is part of logilab-common. |
5 # | 5 # |
6 # logilab-common is free software: you can redistribute it and/or modify it unde
r | 6 # logilab-common is free software: you can redistribute it and/or modify it unde
r |
7 # the terms of the GNU Lesser General Public License as published by the Free | 7 # the terms of the GNU Lesser General Public License as published by the Free |
8 # Software Foundation, either version 2.1 of the License, or (at your option) an
y | 8 # Software Foundation, either version 2.1 of the License, or (at your option) an
y |
9 # later version. | 9 # later version. |
10 # | 10 # |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 | 112 |
113 ENABLE_DBC = False | 113 ENABLE_DBC = False |
114 FILE_RESTART = ".pytest.restart" | 114 FILE_RESTART = ".pytest.restart" |
115 | 115 |
116 import os, sys, re | 116 import os, sys, re |
117 import os.path as osp | 117 import os.path as osp |
118 from time import time, clock | 118 from time import time, clock |
119 import warnings | 119 import warnings |
120 import types | 120 import types |
121 from inspect import isgeneratorfunction, isclass | 121 from inspect import isgeneratorfunction, isclass |
| 122 from contextlib import contextmanager |
122 | 123 |
123 from logilab.common.fileutils import abspath_listdir | 124 from logilab.common.fileutils import abspath_listdir |
124 from logilab.common import textutils | 125 from logilab.common import textutils |
125 from logilab.common import testlib, STD_BLACKLIST | 126 from logilab.common import testlib, STD_BLACKLIST |
126 # use the same unittest module as testlib | 127 # use the same unittest module as testlib |
127 from logilab.common.testlib import unittest, start_interactive_mode | 128 from logilab.common.testlib import unittest, start_interactive_mode |
| 129 from logilab.common.deprecation import deprecated |
128 import doctest | 130 import doctest |
129 | 131 |
130 import unittest as unittest_legacy | 132 import unittest as unittest_legacy |
131 if not getattr(unittest_legacy, "__package__", None): | 133 if not getattr(unittest_legacy, "__package__", None): |
132 try: | 134 try: |
133 import unittest2.suite as unittest_suite | 135 import unittest2.suite as unittest_suite |
134 except ImportError: | 136 except ImportError: |
135 sys.exit("You have to install python-unittest2 to use this module") | 137 sys.exit("You have to install python-unittest2 to use this module") |
136 else: | 138 else: |
137 import unittest.suite as unittest_suite | 139 import unittest.suite as unittest_suite |
138 | 140 |
139 try: | 141 try: |
140 import django | 142 import django |
141 from logilab.common.modutils import modpath_from_file, load_module_from_modp
ath | 143 from logilab.common.modutils import modpath_from_file, load_module_from_modp
ath |
142 DJANGO_FOUND = True | 144 DJANGO_FOUND = True |
143 except ImportError: | 145 except ImportError: |
144 DJANGO_FOUND = False | 146 DJANGO_FOUND = False |
145 | 147 |
146 CONF_FILE = 'pytestconf.py' | 148 CONF_FILE = 'pytestconf.py' |
147 | 149 |
148 ## coverage hacks, do not read this, do not read this, do not read this | 150 ## coverage pausing tools |
149 | 151 |
150 # hey, but this is an aspect, right ?!!! | 152 @contextmanager |
| 153 def replace_trace(trace=None): |
| 154 """A context manager that temporary replaces the trace function""" |
| 155 oldtrace = sys.gettrace() |
| 156 sys.settrace(trace) |
| 157 try: |
| 158 yield |
| 159 finally: |
| 160 # specific hack to work around a bug in pycoverage, see |
| 161 # https://bitbucket.org/ned/coveragepy/issue/123 |
| 162 if (oldtrace is not None and not callable(oldtrace) and |
| 163 hasattr(oldtrace, 'pytrace')): |
| 164 oldtrace = oldtrace.pytrace |
| 165 sys.settrace(oldtrace) |
| 166 |
| 167 |
| 168 def pause_trace(): |
| 169 """A context manager that temporary pauses any tracing""" |
| 170 return replace_trace() |
| 171 |
151 class TraceController(object): | 172 class TraceController(object): |
152 nesting = 0 | 173 ctx_stack = [] |
153 | 174 |
| 175 @classmethod |
| 176 @deprecated('[lgc 0.63.1] Use the pause_trace() context manager') |
154 def pause_tracing(cls): | 177 def pause_tracing(cls): |
155 if not cls.nesting: | 178 cls.ctx_stack.append(pause_trace()) |
156 cls.tracefunc = staticmethod(getattr(sys, '__settrace__', sys.settra
ce)) | 179 cls.ctx_stack[-1].__enter__() |
157 cls.oldtracer = getattr(sys, '__tracer__', None) | |
158 sys.__notrace__ = True | |
159 cls.tracefunc(None) | |
160 cls.nesting += 1 | |
161 pause_tracing = classmethod(pause_tracing) | |
162 | 180 |
| 181 @classmethod |
| 182 @deprecated('[lgc 0.63.1] Use the pause_trace() context manager') |
163 def resume_tracing(cls): | 183 def resume_tracing(cls): |
164 cls.nesting -= 1 | 184 cls.ctx_stack.pop().__exit__(None, None, None) |
165 assert cls.nesting >= 0 | |
166 if not cls.nesting: | |
167 cls.tracefunc(cls.oldtracer) | |
168 delattr(sys, '__notrace__') | |
169 resume_tracing = classmethod(resume_tracing) | |
170 | 185 |
171 | 186 |
172 pause_tracing = TraceController.pause_tracing | 187 pause_tracing = TraceController.pause_tracing |
173 resume_tracing = TraceController.resume_tracing | 188 resume_tracing = TraceController.resume_tracing |
174 | 189 |
175 | 190 |
176 def nocoverage(func): | 191 def nocoverage(func): |
| 192 """Function decorator that pauses tracing functions""" |
177 if hasattr(func, 'uncovered'): | 193 if hasattr(func, 'uncovered'): |
178 return func | 194 return func |
179 func.uncovered = True | 195 func.uncovered = True |
| 196 |
180 def not_covered(*args, **kwargs): | 197 def not_covered(*args, **kwargs): |
181 pause_tracing() | 198 with pause_trace(): |
182 try: | |
183 return func(*args, **kwargs) | 199 return func(*args, **kwargs) |
184 finally: | |
185 resume_tracing() | |
186 not_covered.uncovered = True | 200 not_covered.uncovered = True |
187 return not_covered | 201 return not_covered |
188 | 202 |
189 | 203 ## end of coverage pausing tools |
190 ## end of coverage hacks | |
191 | 204 |
192 | 205 |
193 TESTFILE_RE = re.compile("^((unit)?test.*|smoketest)\.py$") | 206 TESTFILE_RE = re.compile("^((unit)?test.*|smoketest)\.py$") |
194 def this_is_a_testfile(filename): | 207 def this_is_a_testfile(filename): |
195 """returns True if `filename` seems to be a test file""" | 208 """returns True if `filename` seems to be a test file""" |
196 return TESTFILE_RE.match(osp.basename(filename)) | 209 return TESTFILE_RE.match(osp.basename(filename)) |
197 | 210 |
198 TESTDIR_RE = re.compile("^(unit)?tests?$") | 211 TESTDIR_RE = re.compile("^(unit)?tests?$") |
199 def this_is_a_testdir(dirpath): | 212 def this_is_a_testdir(dirpath): |
200 """returns True if `filename` seems to be a test directory""" | 213 """returns True if `filename` seems to be a test directory""" |
(...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 """Return a sorted sequence of method names found within testCaseClass | 1088 """Return a sorted sequence of method names found within testCaseClass |
1076 """ | 1089 """ |
1077 is_skipped = self._this_is_skipped | 1090 is_skipped = self._this_is_skipped |
1078 classname = testCaseClass.__name__ | 1091 classname = testCaseClass.__name__ |
1079 if classname[0] == '_' or is_skipped(classname): | 1092 if classname[0] == '_' or is_skipped(classname): |
1080 return [] | 1093 return [] |
1081 testnames = super(NonStrictTestLoader, self).getTestCaseNames( | 1094 testnames = super(NonStrictTestLoader, self).getTestCaseNames( |
1082 testCaseClass) | 1095 testCaseClass) |
1083 return [testname for testname in testnames if not is_skipped(testname)] | 1096 return [testname for testname in testnames if not is_skipped(testname)] |
1084 | 1097 |
| 1098 |
| 1099 # The 2 functions below are modified versions of the TestSuite.run method |
| 1100 # that is provided with unittest2 for python 2.6, in unittest2/suite.py |
| 1101 # It is used to monkeypatch the original implementation to support |
| 1102 # extra runcondition and options arguments (see in testlib.py) |
| 1103 |
1085 def _ts_run(self, result, runcondition=None, options=None): | 1104 def _ts_run(self, result, runcondition=None, options=None): |
1086 self._wrapped_run(result,runcondition=runcondition, options=options) | 1105 self._wrapped_run(result, runcondition=runcondition, options=options) |
1087 self._tearDownPreviousClass(None, result) | 1106 self._tearDownPreviousClass(None, result) |
1088 self._handleModuleTearDown(result) | 1107 self._handleModuleTearDown(result) |
1089 return result | 1108 return result |
1090 | 1109 |
1091 def _ts_wrapped_run(self, result, debug=False, runcondition=None, options=None): | 1110 def _ts_wrapped_run(self, result, debug=False, runcondition=None, options=None): |
1092 for test in self: | 1111 for test in self: |
1093 if result.shouldStop: | 1112 if result.shouldStop: |
1094 break | 1113 break |
1095 if unittest_suite._isnotsuite(test): | 1114 if unittest_suite._isnotsuite(test): |
1096 self._tearDownPreviousClass(test, result) | 1115 self._tearDownPreviousClass(test, result) |
1097 self._handleModuleFixture(test, result) | 1116 self._handleModuleFixture(test, result) |
1098 self._handleClassSetUp(test, result) | 1117 self._handleClassSetUp(test, result) |
1099 result._previousTestClass = test.__class__ | 1118 result._previousTestClass = test.__class__ |
1100 if (getattr(test.__class__, '_classSetupFailed', False) or | 1119 if (getattr(test.__class__, '_classSetupFailed', False) or |
1101 getattr(result, '_moduleSetUpFailed', False)): | 1120 getattr(result, '_moduleSetUpFailed', False)): |
1102 continue | 1121 continue |
1103 | 1122 |
| 1123 # --- modifications to deal with _wrapped_run --- |
| 1124 # original code is: |
| 1125 # |
| 1126 # if not debug: |
| 1127 # test(result) |
| 1128 # else: |
| 1129 # test.debug() |
1104 if hasattr(test, '_wrapped_run'): | 1130 if hasattr(test, '_wrapped_run'): |
1105 try: | 1131 try: |
1106 test._wrapped_run(result, debug, runcondition=runcondition, opti
ons=options) | 1132 test._wrapped_run(result, debug, runcondition=runcondition, opti
ons=options) |
1107 except TypeError: | 1133 except TypeError: |
1108 test._wrapped_run(result, debug) | 1134 test._wrapped_run(result, debug) |
1109 elif not debug: | 1135 elif not debug: |
1110 try: | 1136 try: |
1111 test(result, runcondition, options) | 1137 test(result, runcondition, options) |
1112 except TypeError: | 1138 except TypeError: |
1113 test(result) | 1139 test(result) |
1114 else: | 1140 else: |
1115 test.debug() | 1141 test.debug() |
| 1142 # --- end of modifications to deal with _wrapped_run --- |
| 1143 return result |
| 1144 |
| 1145 if sys.version_info >= (2, 7): |
| 1146 # The function below implements a modified version of the |
| 1147 # TestSuite.run method that is provided with python 2.7, in |
| 1148 # unittest/suite.py |
| 1149 def _ts_run(self, result, debug=False, runcondition=None, options=None): |
| 1150 topLevel = False |
| 1151 if getattr(result, '_testRunEntered', False) is False: |
| 1152 result._testRunEntered = topLevel = True |
| 1153 |
| 1154 self._wrapped_run(result, debug, runcondition, options) |
| 1155 |
| 1156 if topLevel: |
| 1157 self._tearDownPreviousClass(None, result) |
| 1158 self._handleModuleTearDown(result) |
| 1159 result._testRunEntered = False |
| 1160 return result |
1116 | 1161 |
1117 | 1162 |
1118 def enable_dbc(*args): | 1163 def enable_dbc(*args): |
1119 """ | 1164 """ |
1120 Without arguments, return True if contracts can be enabled and should be | 1165 Without arguments, return True if contracts can be enabled and should be |
1121 enabled (see option -d), return False otherwise. | 1166 enabled (see option -d), return False otherwise. |
1122 | 1167 |
1123 With arguments, return False if contracts can't or shouldn't be enabled, | 1168 With arguments, return False if contracts can't or shouldn't be enabled, |
1124 otherwise weave ContractAspect with items passed as arguments. | 1169 otherwise weave ContractAspect with items passed as arguments. |
1125 """ | 1170 """ |
(...skipping 19 matching lines...) Expand all Loading... |
1145 | 1190 |
1146 if sys.version_info >= (2, 4): | 1191 if sys.version_info >= (2, 4): |
1147 doctest.DocTestCase.__bases__ = (testlib.TestCase,) | 1192 doctest.DocTestCase.__bases__ = (testlib.TestCase,) |
1148 # XXX check python2.6 compatibility | 1193 # XXX check python2.6 compatibility |
1149 #doctest.DocTestCase._cleanups = [] | 1194 #doctest.DocTestCase._cleanups = [] |
1150 #doctest.DocTestCase._out = [] | 1195 #doctest.DocTestCase._out = [] |
1151 else: | 1196 else: |
1152 unittest.FunctionTestCase.__bases__ = (testlib.TestCase,) | 1197 unittest.FunctionTestCase.__bases__ = (testlib.TestCase,) |
1153 unittest.TestSuite.run = _ts_run | 1198 unittest.TestSuite.run = _ts_run |
1154 unittest.TestSuite._wrapped_run = _ts_wrapped_run | 1199 unittest.TestSuite._wrapped_run = _ts_wrapped_run |
OLD | NEW |