我最终编写了两个新类,继承自 unittest.TextTestResult 和 unittest.TextTestRunner。这样,我可以这样运行 main:
unittest.main(testRunner=xmlrunner.XMLTestRunner(...))
我超载了unittest.TextTestRunner 的__init__ 和来自unittest.TextTestResult 的那些:
addSuccess()
addError()
addFailure()
addSubTest()
例如:
def addSuccess(self, test):
super().addSuccess(test)
[... store the test into list, dictionary, whatever... ]
由于这些add*() 函数是在实际测试中调用的,所以我可以将它们存储在一个全局列表中,并在XMLTestRunner.run() 的末尾解析它们:
def run(self, test):
result = super().run(test)
self.save_xml_report(result)
return result
请注意,这些函数通常在/usr/lib/python3.4/unittest/runner.py 中定义。
警告说明:通过使用传递unittest.main() 的testRunner 参数的实际对象,如图所示,启动python 时给出的命令行参数将被忽略。例如,使用-v 参数增加详细级别将被忽略。这是因为在/usr/lib/python3.4/unittest/main.py 中定义的TestProgram 类检测unittest.main() 是否在testRunner 是类或对象的情况下运行(请参阅文件末尾附近的runTests())。如果你只开这样的课:
unittest.main(testRunner=xmlrunner.XMLTestRunner)
然后解析命令行参数。但是你传递了一个实例化的对象(就像我需要的那样),runTests() 将按原样使用它。因此,我不得不自己在 XMLTestRunner.__init__() 中解析参数:
# Similar to what /usr/lib/python3.4/unittest/main.py's TestProgram._getParentArgParser() does.
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-v', '--verbose', dest='verbosity',
action='store_const', const=2, default=1, # Add default=1, not present in _getParentArgParser()
help='Verbose output')
parser.add_argument('-q', '--quiet', dest='verbosity',
action='store_const', const=0,
help='Quiet output')
parser.add_argument('-f', '--failfast', dest='failfast',
action='store_true',
help='Stop on first fail or error')
parser.add_argument('-c', '--catch', dest='catchbreak',
action='store_true',
help='Catch ctrl-C and display results so far')
parser.add_argument('-b', '--buffer', dest='buffer',
action='store_true',
help='Buffer stdout and stderr during tests')