在Python中运行测试包中的单元测试
我正在用Python写一个解析器,专门处理一种特殊的文本文件格式。为了了解怎么组织代码,我查看了Python标准库里JSON解析器的源代码(在Python/Lib/json
目录下)。
在这个json目录里,有一个tests
目录,里面放了一些单元测试。我把这些JSON测试替换成了我的测试,但现在我不知道该怎么运行它们。
在这个目录里,有一个__init__.py
文件,这让它成为一个模块。在这个文件里,有一段代码是用来运行测试的:
here = os.path.dirname(__file__)
def test_suite():
suite = additional_tests()
loader = unittest.TestLoader()
for fn in os.listdir(here):
if fn.startswith("test") and fn.endswith(".py"):
modname = "json.tests." + fn[:-3]
__import__(modname)
module = sys.modules[modname]
suite.addTests(loader.loadTestsFromModule(module))
return suite
def additional_tests():
suite = unittest.TestSuite()
for mod in (json, json.encoder, json.decoder):
suite.addTest(doctest.DocTestSuite(mod))
suite.addTest(TestPyTest('test_pyjson'))
suite.addTest(TestCTest('test_cjson'))
return suite
def main():
suite = test_suite()
runner = unittest.TextTestRunner()
runner.run(suite)
if __name__ == '__main__':
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
main()
我现在的问题是,这些单元测试是怎么执行的?我有点困惑,因为if __name__ == '__main__':
这个条件只有在直接调用这个文件时才会成立,而不是作为模块被导入。不过,既然它在模块的__init__.py
文件里,导入后应该就会执行。
在Python控制台里用import tests
命令,是否会启动所有的单元测试呢?
1 个回答
首先:目录中的 __init__.py
文件表示这个目录是一个包,而里面所有以 .py
结尾的文件都是模块。
其次:要验证 __name__ == '__main__'
这个条件,你需要执行这个文件。所以简单的 import
是不够的。
如果你想了解更多关于包和模块结构的内容,建议你阅读官方的 Python 文档。
单元测试被组织成测试套件,测试套件可以包含一个或多个测试用例,而每个测试用例又可以包含一个或多个测试。
这些测试通常是从测试用例派生的类中的方法。你可以通过定义一个 runTest()
方法来运行测试,或者定义多个以 test_*
开头的方法,这些方法会自动执行。要执行单元测试,你可以使用方便的函数 unittest.main()
,这个函数基本上会根据默认规则构建一个测试套件、测试结果和测试运行器对象。
你的单元测试的执行是由测试运行器对象完成的。标准的测试运行器类是 TextTestRunner
,它使用 TextTestResult
类来存储测试结果,并将结果打印到 stdout
。有关 unittest.main()
的最简单用法,请参见官方单元测试文档。
总结
1) 单元测试基本上是一个包含一个或多个测试用例的测试套件:
TestSuite <---executed by--- TestRunner
+ TestCaseA |
+test_a() |
+test_b() stores test-results
... into
+test_z() |
+ TestCaseB V
+ TestCaseC TestResult
2) 测试用例是 unittest.TestCase
的子类。你可以使用加载器(例如:unittest.defaultTestLoader
)来创建一个测试套件,加载器基本上是一个测试套件的工厂,或者你也可以手动添加测试用例(suite.addTest(test) / suite.addTests(tests)
- tests
可以是 TestCases
或者其他 TestSuites
),或者结合这两种方法。
3) 要执行一个测试套件,你需要使用一个 unittest.TestRunner
对象,它会把结果保存在一个 unittest.TestResult
对象中。
通常你会使用 unittest.TextTestRunner
对象来简单地输出测试结果到标准输出。
这正是你在主程序中发生的事情:
def main():
suite = test_suite() #1 create a TestSuite object
runner = unittest.TextTestRunner() #2 create a TextTestRunner object
runner.run(suite) #3 executes the TestSuite with TestSuite
# build by the function test_suite()
要执行你的测试套件,你需要运行 python __init__.py
。