Python unittest模块中unittest.main()的含义

时间:2014-01-08 10:19:09

标签: python unit-testing python-internals

我试图在Python中学习单元测试,特别是unittest模块。

请考虑以下几行:

import unittest

class abc(unittest.TestCase):
    def xyz():
      ...

if __name__ == "__main__":
    unittest.main()

由于调用了unittest.main(),我可以看到我的所有测试用例都在运行。

我很想知道这个调用是如何使所有测试用例运行的。

我知道,因为我为每个测试类继承了unittest.TestCase,所以它正在做所有的魔术。任何见解?

2 个答案:

答案 0 :(得分:7)

在内部,unittest.main()使用一些技巧来确定包含对main()的调用的模块名称(源文件)。

然后导入这些模块,检查它,获取可以测试的所有类和函数的列表(根据配置),然后为每个模块创建一个测试用例。

当列表准备就绪时,它依次执行每个测试。

答案 1 :(得分:5)

与unittest相关的主要实际上是TestProgram的一个实例,在实例化时会运行所有测试。

以下是从http://pythonhosted.org/gchecky/unittest-pysrc.html

的unittest来源复制的相关代码
735  class TestProgram: 
752 -    def __init__(self, module='__main__', defaultTest=None, 
753                   argv=None, testRunner=None, testLoader=defaultTestLoader): 
754          if type(module) == type(''): 
755              self.module = __import__(module) 
756              for part in module.split('.')[1:]: 
757                  self.module = getattr(self.module, part) 
758          else: 
759              self.module = module 
760          if argv is None: 
761              argv = sys.argv 
762          self.verbosity = 1 
763          self.defaultTest = defaultTest 
764          self.testRunner = testRunner 
765          self.testLoader = testLoader 
766          self.progName = os.path.basename(argv[0]) 
767          self.parseArgs(argv) 
768          self.runTests() 
769   
770 -    def usageExit(self, msg=None): 
771          if msg: print msg 
772          print self.USAGE % self.__dict__ 
773          sys.exit(2) 
774   
775 -    def parseArgs(self, argv): 
776          import getopt 
777          try: 
778              options, args = getopt.getopt(argv[1:], 'hHvq', 
779                                            ['help','verbose','quiet']) 
780              for opt, value in options: 
781                  if opt in ('-h','-H','--help'): 
782                      self.usageExit() 
783                  if opt in ('-q','--quiet'): 
784                      self.verbosity = 0 
785                  if opt in ('-v','--verbose'): 
786                      self.verbosity = 2 
787              if len(args) == 0 and self.defaultTest is None: 
788                  self.test = self.testLoader.loadTestsFromModule(self.module) 
789                  return 
790              if len(args) > 0: 
791                  self.testNames = args 
792              else: 
793                  self.testNames = (self.defaultTest,) 
794              self.createTests() 
795          except getopt.error, msg: 
796              self.usageExit(msg) 
797   
798 -    def createTests(self): 
799          self.test = self.testLoader.loadTestsFromNames(self.testNames, 
800                                                         self.module) 
801   
802 -    def runTests(self): 
803          if self.testRunner is None: 
804              self.testRunner = TextTestRunner(verbosity=self.verbosity) 
805          result = self.testRunner.run(self.test) 
806          sys.exit(not result.wasSuccessful()) 
807   
808  main = TestProgram 

因此,当您执行unittest.main()时,会创建TestProgram的对象,该对象在第768行调用self.runTests()。构造函数还将当前文件作为包含测试的默认模块({ {1}})。调用module='__main__'后,它会调用runTests()。当您引用self.testrunner.run()类的“运行”方法时,您会发现它实际运行并报告您的所有测试结果。当您调用unittest.main()时,测试发现由TextTestRunner在第775行完成。第798行的TestProgram.parseArgs实际上负责发现所有测试用例并创建测试套件。这就是魔术。