在Python中运行测试包中的单元测试

时间:2012-01-04 14:26:10

标签: python unit-testing

我正在尝试用Python编写一个特殊文本文件格式的解析器。为了了解如何构造代码,我查看了JSON解析器的源代码,它是Python标准库(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__': if子句将验证为true。但是,由于它位于模块的__init__.py文件中,因此应在导入后立即执行。

python控制台中的import tests是否应该启动所有单元测试?

1 个答案:

答案 0 :(得分:6)

首先:目录中的__init__.py文件将目录标记为包,其中以.py结尾的所有其他文件都是模块。

第二:要验证__name__ == '__main__'条件,您必须执行该文件。所以一个简单的import不会做。

关于包和模块结构的进一步问题,我建议你阅读Official Python Documentation on Packages

单元测试结构为测试套件,可包含一个或多个测试套件,其中包含一个或多个测试。

测试通常是TestCase派生类的方法。您可以通过定义runTest()方法或定义多个test_*方法来运行测试,这些方法将自动执行。要执行Unittest,您可以使用便捷函数unittest.main(),它基本上尝试使用默认规则构建一个testsuite,testresult和testrunner对象。

您的unittest本身的执行由testrunner对象完成。标准testrunner类是TextTestRunner,它使用TextTestResult - 类来存储测试结果并将它们打印到stdout。有关最简单的变体,请参阅Official unittest Documentation for unittest.main()

摘要

1)单元测试基本上是一个包含一个或多个TestCase的TestSuite:

TestSuite      <---executed by--- TestRunner
   + TestCaseA                        |
       +test_a()                      |
       +test_b()             stores test-results 
           ...                      into
       +test_z()                      |
    + TestCaseB                       V
    + TestCaseC                  TestResult

2) TestCases是unittest.TestCase的子类。您可以使用加载器(例如:unittest.defaultTestLoader)创建TestSuite,该加载器基本上是测试套件的工厂,或者您可以手动添加TestCases(suite.addTest(test) / suite.addTests(tests) - tests可能是{ {1}}或甚至其他TestCases)或将这两种方法结合起来。

3)要执行测试套件,请使用TestSuites - 对象,将结果保存在unittest.TestRunner对象中。

Normaly你会使用unittest.TestResult - object来获得测试结果到stdout的简单输出。

令人兴奋的是你的主程序中也会发生什么:

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()