42

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

考虑以下几行:

import unittest

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

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

由于对unittest.main().

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

我知道,因为我从unittest.TestCase每个测试类继承,它正在做所有的魔法。有什么见解吗?

4

2 回答 2

19

unittest关联的main实际上是 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

因此,当您执行时,会创建一个在第 768 行调用unittest.main()的对象。构造函数还将您的当前文件作为包含测试 ( ) 的默认模块。TestProgramself.runTests()module='__main__'

runTests()被调用时,它依次调用self.testrunner.run(). 当您参考TextTestRunner类的“运行”方法时,您会发现它实际上运行并报告了您所有的测试结果。

TestProgram.parseArgs当您调用 unittest.main() 时,测试发现在第 775 行完成。self.createTests第 798 行实际上负责发现所有测试用例并创建测试套件。这就是所有的魔法。

于 2014-01-08T10:43:44.423 回答
14

在内部,unittest.main()正在使用一些技巧来找出包含对main().

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

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

于 2014-01-08T10:48:22.037 回答