我正在使用Python的(3.4.1)unittest
模块进行单元测试。
我使用导入加载所有测试模块文件,然后运行unittest.main():
import unittest
import testing_module1
import testing_module2
# [...]
if __name__ == '__main__':
unittest.main()
这对我来说非常合适,因为它很简单并且尊重我用来控制详细程度或运行哪些测试的命令行参数。
我想继续输出相同的信息,但我想从结果中生成XML文件。我尝试了xmlrunner(https://github.com/xmlrunner/unittest-xml-reporting/)但是:
我想用我需要的格式生成XML(我不介意手动操作),但对测试的运行方式的改动很小。
我有什么选择?
unittest.main()
之后提取测试结果并解析它。这里的问题是,unittest.main()
似乎在它完成时退出,因此任何代码都不会被执行。有什么建议吗?
谢谢!
答案 0 :(得分:1)
我最后写了两个新类,继承自unittest.TextTestResult
和unittest.TextTestRunner
。这样,我可以像那样运行main:
unittest.main(testRunner=xmlrunner.XMLTestRunner(...))
我重载了unittest.TextTestRunner
的{{1}}以及来自__init__
的<{1}}:
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
的{{1}}参数的实际对象,将忽略启动python时给出的命令行参数。例如,忽略使用unittest.main()
参数增加详细级别。这是因为testRunner
中定义的-v
类会检测TestProgram
是否在/usr/lib/python3.4/unittest/main.py
作为类或对象的情况下运行(请参阅unittest.main()
附近的testRunner
的文件)。如果你只给这样一个类:
runTests()
然后解析命令行参数。但是你传递了一个实例化的对象(就像我需要的那样),unittest.main(testRunner=xmlrunner.XMLTestRunner)
将只是按原样使用它。因此,我必须在runTests()
:
XMLTestRunner.__init__()
答案 1 :(得分:0)
这对您有何帮助?在StringIO中捕获unittest的输出,该输出转到sys.stderr。在unittest.main之后继续添加`exit = False&#39;。根据需要读取捕获的输出和处理。概念证明:
import contextlib
import io
import sys
import unittest
class Mytest(unittest.TestCase):
def test_true(self):
self.assertTrue(True)
@contextlib.contextmanager
def err_to(file):
old_err = sys.stderr
sys.stderr = file
yield
sys.stderr = old_err
if __name__ == '__main__':
result = io.StringIO()
with err_to(result):
unittest.main(exit=False)
result.seek(0)
print(result.read())
打印(到sys.stdout)
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
注意:contextlib有redirect_stdout,但不是redirect_stderr。以上比contextlib代码更简单。以上假设没有单一测试未捕获的例外情况。请参阅contextlib.contextmanager doc以添加try:except:finally。我把它留给你。
答案 2 :(得分:0)
从unittest lib捕获FAIL事件时,我也遇到了同样的问题。遵循big_gie的回答,此代码出现了:
文件testFileName_1.py
import unittest
class TestClassToTestSth(unittest.TestCase):
def test_One(self):
self.AssertEqual(True, False, 'Hello world')
import unittest
from io import StringIO
import testFileName_1
def suites():
return [
# your testCase classes, for example
testFileName_1.TestClassToTestSth,
testFileName_445.TestClassToTestSomethingElse,
]
class TextTestResult(unittest.TextTestResult):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.slack = Slack('data-engineering-tests')
def addFailure(self, test, err):
super().addFailure(test, err)
# Whatever you want here
print(err, test)
print(self.failures)
class TextTestRunner(unittest.TextTestRunner):
resultclass = TextTestResult
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
loader = unittest.TestLoader()
suite = unittest.TestSuite()
stream = StringIO()
for test_case in suites():
suite.addTests(loader.loadTestsFromTestCase(test_case))
runner = TextTestRunner(stream=stream)
result = runner.run(suite)
stream.seek(0)
print(stream.read())