42

unittestPython、特にモジュールで単体テストを学ぼうとしていました。

次の行を検討してください。

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

そのため、を実行するunittest.main()と、768 行で呼び出される のオブジェクトTestProgramが作成されself.runTests()ます。また、コンストラクターは、現在のファイルを、テスト ( ) を含む既定のモジュールとして取得しますmodule='__main__'

runTests()呼び出されると、次に を呼び出しますself.testrunner.run()。クラスの「実行」メソッドを参照すると、TextTestRunner実際に実行され、すべてのテスト結果が報告されることがわかります。

TestProgram.parseArgsunittest.main() を呼び出すと、775 行目でテストの検出が行われます。self.createTests798 行目は、実際にはすべてのテスト ケースを検出し、テスト スイートを作成する役割を果たします。これがすべての魔法です。

于 2014-01-08T10:43:44.423 に答える
14

内部的にunittest.main()は、への呼び出しを含むモジュール (ソース ファイル) の名前を把握するためにいくつかのトリックを使用していますmain()

次に、このモジュールをインポートして調べ、(構成に従って) テストできるすべてのクラスと関数のリストを取得し、それぞれのテスト ケースを作成します。

リストの準備ができると、各テストが順番に実行されます。

于 2014-01-08T10:48:22.037 に答える