как автоматически добавить дюжину тестовых случаев в набор тестов в python

у меня есть дюжина тестовых случаев в разных папках. В корневом каталоге есть тестовый раннер.

unittest\
  package1\
    test1.py
    test2.py
  package2\
    test3.py
    test4.py
  testrunner.py

В настоящее время я добавил четыре тестовых примера вручную в набор тестов.

import unittest
from package1.test1 import Test1
from package1.test2 import Test2
from package2.test3 import Test3
from package2.test4 import Test4

suite = unittest.TestSuite()
suite.addTests(unittest.makeSuite(Test1))
suite.addTests(unittest.makeSuite(Test2))
suite.addTests(unittest.makeSuite(Test3))
suite.addTests(unittest.makeSuite(Test4))

result = unittest.TextTestRunner(verbosity=2).run(suite)
if not result.wasSuccessful():
  sys.exit(1)

Как позволить тестировщику автоматически тестировать все тестовые случаи? Такие как:

for testCase in findTestCases():
  suite.addTests(testCase)

person stanleyxu2005    schedule 01.07.2010    source источник


Ответы (3)


Вышеупомянутые модули хороши, но NoseTests могут быть забавными при попытке ввести параметры, и это также быстрее и хорошо вписывается в другой модуль.

import os, unittest

class Tests():   

    def suite(self): #Function stores all the modules to be tested


        modules_to_test = []
        test_dir = os.listdir('.')
        for test in test_dir:
            if test.startswith('test') and test.endswith('.py'):
                modules_to_test.append(test.rstrip('.py'))

        alltests = unittest.TestSuite()
        for module in map(__import__, modules_to_test):
            module.testvars = ["variables you want to pass through"]
            alltests.addTest(unittest.findTestCases(module))
        return alltests

if __name__ == '__main__':
    MyTests = Tests()
    unittest.main(defaultTest='MyTests.suite')

Если вы хотите добавить результаты в файл журнала, добавьте это в конец вместо этого:

if __name__ == '__main__':
    MyTests = Tests()
    log_file = 'log_file.txt'
    f = open(log_file, "w") 
    runner = unittest.TextTestRunner(f)
    unittest.main(defaultTest='MyTests.suite', testRunner=runner)

Также внизу модулей, которые вы тестируете, поместите такой код:

class SomeTestSuite(unittest.TestSuite):

    # Tests to be tested by test suite
    def makeRemoveAudioSource():
        suite = unittest.TestSuite()
        suite.AddTest(TestSomething("TestSomeClass"))

        return suite

    def suite():
        return unittest.makeSuite(TestSomething)

if __name__ == '__main__':
    unittest.main()
person chrisg    schedule 02.07.2010

На мой взгляд, вам следует переключиться на unittest2 или другие среды тестирования с функциями обнаружения. Тесты Discovery — действительно разумный способ их запуска.

Наиболее известны:

Например, с помощью Nosetest достаточно запустить nosetests из корневого каталога проекта, и он обнаружит и запустит все найденные модульные тесты. Довольно просто.

Обратите также внимание, что unittest2 будет включен в Python 2.7 (и, я думаю, до версии 2.4).

person pygabriel    schedule 01.07.2010
comment
Библиотека unittest2 кажется очень интересным инструментом. спасибо за информацию. - person stanleyxu2005; 02.07.2010

То, что я сделал, это скрипт-оболочка, который запускает отдельные тестовые файлы:

Основная оболочка run_tests.py:

#!/usr/bin/env python3
# Usage: ./run_tests.py -h http://example.com/ tests/**/*.py
import sys, unittest, argparse, inspect, logging

if __name__ == '__main__':
    # Parse arguments.
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument("-v", "--verbose",  action="store_true", dest="verbose",  help="increase output verbosity" )
    parser.add_argument("-d", "--debug",    action="store_true", dest="debug",    help="show debug messages" )
    parser.add_argument("-h", "--host",     action="store",      dest="host",     help="Destination host" )
    parser.add_argument('files', nargs='*')
    args = parser.parse_args()

    # Load files from the arguments.
    for filename in args.files:
        exec(open(filename).read())

    # See: http://codereview.stackexchange.com/q/88655/15346
    def make_suite(tc_class):
        testloader = unittest.TestLoader()
        testnames = testloader.getTestCaseNames(tc_class)
        suite = unittest.TestSuite()
        for name in testnames:
            suite.addTest(tc_class(name, cargs=args))
        return suite

    # Add all tests.
    alltests = unittest.TestSuite()
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(obj) and name.startswith("FooTest") and len(name) > len("FooTest"):
            alltests.addTest(make_suite(obj))

    # Run tests.
    result = unittest.TextTestRunner(verbosity=2).run(alltests)
    sys.exit(not result.wasSuccessful())

Затем еще одна обертка для тестов:

class FooTest(unittest.TestCase):
    def __init__(self, *args, cargs=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.vdisplay = Xvfb(width=1280, height=720)
        self.vdisplay.start()
        self.args=cargs
        self.log=logging

    def setUp(self):
        self.site = webdriver.Firefox()

    def kill(self):
        self.vdisplay.stop()

Тогда каждый тест в отдельных файлах будет выглядеть так:

import sys, os, unittest
from FooTest import FooTest

class FooTest1(FooTest):

    def test_homepage(self):
        self.site.get(self.base_url + "/")
        log.debug("Home page loaded.")

Затем вы можете легко запускать тесты из оболочки, например:

$ ./run_tests.py -h http://example.com/ test1.py test2.py

Вы можете использовать подстановочный знак, чтобы указать все файлы в определенных каталогах, или использовать новый опция подстановки (**) для рекурсивного запуска всех тестов (включить shopt -s globstar).

person kenorb    schedule 05.05.2015