Значение unittest.main() в модуле unittest Python - программирование
Подтвердить что ты не робот

Значение unittest.main() в модуле unittest Python

Я пытался изучить модульное тестирование в Python, в частности модуль unittest.

Рассмотрим следующие строки:

import unittest

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

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

Я мог видеть, что все мои тестовые сценарии запущены из-за вызова unittest.main().

Мне было просто интересно узнать, как этот вызов запускает все тестовые сценарии.

Я знаю, так как я наследую от unittest.TestCase для каждого тестового класса, он делает все волшебство. Любые идеи?

4b9b3361

Ответ 1

Внутри unittest.main() используется несколько трюков для определения имени модуля (исходного файла), содержащего вызов main().

Затем он импортирует эти модули, проверяет его, получает список всех классов и функций, которые могут быть проверками (в соответствии с конфигурацией), а затем создает тестовый пример для каждого из них.

Когда список будет готов, он будет выполнять каждый тест по очереди.

Ответ 2

main, связанный с unittest, фактически является экземпляром TestProgram, который при создании экземпляра запускает все ваши тесты.

Ниже приведен код, скопированный из источника unittest в 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() создается объект TestProgram, который вызывает self.runTests() в строке 768. Конструктор также переносит ваш текущий файл в качестве модуля по умолчанию, содержащего тесты (module='__main__'). Когда вызывается runTests(), он, в свою очередь, вызывает self.testrunner.run(). Когда вы ссылаетесь на метод "run" класса TextTestRunner, вы обнаружите, что он действительно запускается и сообщает все ваши результаты теста. Открытие теста выполняется TestProgram.parseArgs в строке 775, когда вы вызываете unittest.main(). self.createTests в строке 798 фактически отвечает за обнаружение всех ваших тестовых примеров и создание набора тестов. Это все волшебство.