web-dev-qa-db-ja.com

Python unittestモジュールでのunittest.main()の意味

私はPythonでのユニットテスト、特にunittestモジュールを学ぼうとしていました。

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

_import unittest

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

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

unittest.main()を呼び出したため、すべてのテストケースが実行されていることがわかりました。

この呼び出しによってすべてのテストケースがどのように実行されるのか知りたいと思いました。

私はすべてのテストクラスについて_unittest.TestCase_から継承しているので、すべての魔法を実行していることを知っています。洞察はありますか?

25
himalayanZephyr

unittestに関連付けられているメインは、実際には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 
_

したがって、unittest.main()を実行すると、768行目でself.runTests()を呼び出すTestProgramのオブジェクトが作成されます。コンストラクターは、テストを含むデフォルトモジュールとして現在のファイルも取得します。 (_module='__main__'_)。 runTests()が呼び出されると、次にself.testrunner.run()が呼び出されます。 TextTestRunnerクラスの「run」メソッドを参照すると、実際に実行され、すべてのテスト結果が報告されることがわかります。テスト検出は、unittest.main()を呼び出すときに、行775の_TestProgram.parseArgs_によって実行されます。 798行目の_self.createTests_は、実際にはすべてのテストケースを検出し、テストスイートを作成する責任があります。これがすべての魔法です。

8
praveen

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

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

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

8
Aaron Digulla