Package test_suite :: Module relax_test_runner
[hide private]
[frames] | no frames]

Source Code for Module test_suite.relax_test_runner

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2008,2011,2013-2014,2019 Edward d'Auvergne                    # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Python module imports. 
 23  import dep_check 
 24  from re import search, split 
 25  import sys 
 26  from time import time 
 27  from traceback import print_exception 
 28  from unittest import TextTestRunner 
 29  if dep_check.wx_module: 
 30      import wx 
 31   
 32  # relax module imports. 
 33  from lib.compat import StringIO 
 34  from lib.compat import TextTestResult 
 35  from status import Status; status = Status() 
 36  from test_suite.formatting import divider, format_test_name, test_title 
 37   
 38   
39 -class RelaxTestResult(TextTestResult):
40 """A replacement for the TextTestResult class. 41 42 This class is designed to catch STDOUT and STDERR during the execution of each test and to 43 prepend the output to the failure and error reports normally generated by TextTestRunner. 44 """ 45
46 - def __init__(self, stream, descriptions, verbosity, category=None, timing=False, io_capture=True):
47 """Initialise the RelaxTestResult object with relax specific variables. 48 49 @param stream: The IO stream to write all output to. 50 @type stream: writable object 51 @param descriptions: A flag which if True will cause the test description to be printed out, when the verbosity is > 1. 52 @type descriptions: bool 53 @param verbosity: The verbosity level. 54 @type verbosity: int 55 @keyword category: The type of test being performed, to allow the printouts to be changed. This can be one of 'system', 'unit', 'gui', or 'verification'. 56 @type category: str 57 @keyword timing: A flag which if True will enable timing of individual tests. 58 @type timing: bool 59 @keyword io_capture: A flag which if True will cause all IO to be captured and only printed out for failing or error tests. 60 @type io_capture: bool 61 """ 62 63 # Normal setup. 64 super(RelaxTestResult, self).__init__(stream, descriptions, verbosity) 65 66 # Store the flags and category. 67 self.timing_flag = timing 68 self.io_capture = io_capture 69 self.category = category 70 71 # Set the separator widths. 72 self.separator1 = '=' * status.text_width 73 self.separator2 = '-' * status.text_width
74 75
76 - def addError(self, test, err):
77 """Override of the TestResult.addError() method. 78 79 The STDOUT and STDERR captured text is prepended to the error text here. 80 81 82 @param test: The test object. 83 @type test: TestCase instance 84 @param err: A tuple of values as returned by sys.exc_info(). 85 @type err: tuple of values 86 """ 87 88 # Extra formatting for no IO capture. 89 if not self.io_capture: 90 self.stream.write(self._exc_info_to_string(err, test)) 91 divider('-', width=status.text_width) 92 93 # Execute the base class method to print the 'E' and handle the error. 94 super(RelaxTestResult, self).addError(test, err) 95 96 # Prepend the STDOUT and STDERR messages to the second element of the tuple. 97 if self.io_capture: 98 self.errors[-1] = (self.errors[-1][0], self.capt.getvalue() + self.errors[-1][1]) 99 100 # Write out timing info. 101 if self.timing_flag or not self.io_capture: 102 self.write_time(test.id())
103 104
105 - def addFailure(self, test, err):
106 """Override of the TestResult.addFailure() method. 107 108 The STDOUT and STDERR captured text is prepended to the failure text here. 109 110 111 @param test: The test object. 112 @type test: TestCase instance 113 @param err: A tuple of values as returned by sys.exc_info(). 114 @type err: tuple of values 115 """ 116 117 # Extra formatting for no IO capture. 118 if not self.io_capture: 119 self.stream.write(self._exc_info_to_string(err, test)) 120 divider('-', width=status.text_width) 121 122 # Execute the base class method to print the 'F' and handle the failure. 123 super(RelaxTestResult, self).addFailure(test, err) 124 125 # Prepend the STDOUT and STDERR messages to the second element of the tuple. 126 if self.io_capture: 127 self.failures[-1] = (self.failures[-1][0], self.capt.getvalue() + self.failures[-1][1]) 128 129 # Write out timing info. 130 if self.timing_flag or not self.io_capture: 131 self.write_time(test.id())
132 133
134 - def addSuccess(self, test):
135 """The method for a successful test. 136 137 @param test: The test object. 138 @type test: TestCase instance 139 """ 140 141 # Extra formatting for no IO capture. 142 if not self.io_capture: 143 divider('-', width=status.text_width) 144 145 # Execute the base class method to print the '.'. 146 super(RelaxTestResult, self).addSuccess(test) 147 148 # Write out timing info. 149 if self.timing_flag or not self.io_capture: 150 self.write_time(test.id())
151 152
153 - def startTest(self, test):
154 """Override of the TextTestResult.startTest() method. 155 156 The start of STDOUT and STDERR capture occurs here. 157 """ 158 159 # IO capture. 160 if self.io_capture: 161 # Store the original STDOUT and STDERR for restoring later on. 162 self.orig_stdout = sys.stdout 163 self.orig_stderr = sys.stderr 164 165 # Catch stdout and stderr. 166 self.capt = StringIO() 167 sys.stdout = self.capt 168 sys.stderr = self.capt 169 170 # No capture. 171 else: 172 test_title(format_test_name(test.id()), desc=test.shortDescription(), width=status.text_width) 173 174 # Place the test name in the status object. 175 status.exec_lock.test_name = str(test) 176 177 # Store the starting time. 178 if self.timing_flag or not self.io_capture: 179 self.time = time() 180 181 # Execute the normal startTest method. 182 super(RelaxTestResult, self).startTest(test)
183 184
185 - def stopTest(self, test):
186 """Override of the TextTestResult.stopTest() method. 187 188 The end of STDOUT and STDERR capture occurs here. 189 """ 190 191 # Restore the IO streams. 192 if self.io_capture: 193 sys.stdout = self.orig_stdout 194 sys.stderr = self.orig_stderr
195 196
197 - def write_time(self, test_name):
198 """Write the timing of the test to the stream. 199 200 @param test_name: The TestCase name. 201 @type test_name: str 202 """ 203 204 # Subtract the end time from the start time. 205 self.time -= time() 206 207 # Format the name. 208 test_name = format_test_name(test_name) 209 210 # The printout. 211 if self.category == 'unit': 212 time_str = '%7.2f ms' % (abs(self.time) * 1000) 213 else: 214 time_str = '%7.2f s' % abs(self.time) 215 self.stream.write(' %s for %s\n' % (time_str, test_name))
216 217 218
219 -class GuiTestResult(RelaxTestResult):
220 """A replacement for the TextTestResult class for the GUI.""" 221
222 - def stopTest(self, test):
223 """Override of the RelaxTestResult.stopTest() method. 224 225 The end of STDOUT and STDERR capture occurs here. 226 """ 227 228 # Execute the RelaxTestResult.stopTest() method. 229 super(GuiTestResult, self).stopTest(test) 230 231 # Yield to allow the GUI to be updated. 232 wx.GetApp().Yield(True)
233 234 235
236 -class RelaxTestRunner(TextTestRunner):
237 """A replacement unittest runner. 238 239 This runner is designed to catch STDOUT during the execution of each test and to prepend the 240 output to the failure and error reports normally generated by TextTestRunner. 241 """ 242 243 # Variable for specifying the type of test being performed, to change the printout. 244 category = None 245
246 - def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, timing=False, io_capture=True):
247 """Initialise the class, storing the timing flag. 248 249 @param stream: The IO stream to write all output to. 250 @type stream: writable object 251 @param descriptions: A flag which if True will cause the test description to be printed out, when the verbosity is > 1. 252 @type descriptions: bool 253 @param verbosity: The verbosity level. 254 @type verbosity: int 255 @keyword timing: A flag which if True will enable timing of individual tests. 256 @type timing: bool 257 @keyword io_capture: A flag which if True will cause all IO to be captured and only printed out for failing or error tests. 258 @type io_capture: bool 259 """ 260 261 # Execute the base method (with different Python version compatibility). 262 if (sys.version_info[0] == 3 and sys.version_info[1] == 1) or (sys.version_info[0] == 2 and sys.version_info[1] <= 6): 263 super(RelaxTestRunner, self).__init__(stream=stream, descriptions=descriptions, verbosity=verbosity) 264 else: 265 super(RelaxTestRunner, self).__init__(stream=stream, descriptions=descriptions, verbosity=verbosity, failfast=failfast, buffer=buffer, resultclass=resultclass) 266 267 # Store the flags. 268 self.timing_flag = timing 269 self.io_capture = io_capture
270 271
272 - def _makeResult(self):
273 """Override of the TextTestRunner._makeResult() method.""" 274 275 return RelaxTestResult(self.stream, self.descriptions, self.verbosity, timing=self.timing_flag, io_capture=self.io_capture, category=self.category)
276 277 278
279 -class GuiTestRunner(TextTestRunner):
280 """A replacement unittest runner. 281 282 This runner is designed to catch STDOUT during the execution of each test and to prepend the 283 output to the failure and error reports normally generated by TextTestRunner. 284 """ 285
286 - def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, timing=False, io_capture=True):
287 """Initialise the class, storing the timing flag. 288 289 @param stream: The IO stream to write all output to. 290 @type stream: writable object 291 @param descriptions: A flag which if True will cause the test description to be printed out, when the verbosity is > 1. 292 @type descriptions: bool 293 @param verbosity: The verbosity level. 294 @type verbosity: int 295 @keyword timing: A flag which if True will enable timing of individual tests. 296 @type timing: bool 297 @keyword io_capture: A flag which if True will cause all IO to be captured and only printed out for failing or error tests. 298 @type io_capture: bool 299 """ 300 301 # Execute the base method. 302 if (sys.version_info[0] == 3 and sys.version_info[1] == 1) or (sys.version_info[0] == 2 and sys.version_info[1] <= 6): 303 super(GuiTestRunner, self).__init__(stream=stream, descriptions=descriptions, verbosity=verbosity) 304 else: 305 super(GuiTestRunner, self).__init__(stream=stream, descriptions=descriptions, verbosity=verbosity, failfast=failfast, buffer=buffer, resultclass=resultclass) 306 307 # Store the flags. 308 self.timing_flag = timing 309 self.io_capture = io_capture
310 311
312 - def _makeResult(self):
313 """Override of the TextTestRunner._makeResult() method.""" 314 315 return GuiTestResult(self.stream, self.descriptions, self.verbosity, timing=self.timing_flag, io_capture=self.io_capture)
316