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

him*_*hyr 20 python unit-testing python-internals

我试图用Python学习单元测试,特别是unittest模块.

请考虑以下几行:

import unittest

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

if __name__ == "__main__":
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

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

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

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

pra*_*een 8

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

下面是从单元测试源复制的相关代码http://pythonhosted.org/gchecky/unittest-pysrc.html:

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 
Run Code Online (Sandbox Code Playgroud)

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


Aar*_*lla 8

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

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

列表准备就绪后,它依次执行每个测试.