Создание экземпляра Python unittest.TestCase с аргументами

Я хотел бы перебрать список элементов и выполнить утверждение для каждого из них. Одним из примеров может быть проверка, является ли каждое число в списке нечетным.

TestCase:

class TestOdd(unittest.TestCase):
    def runTest(self):
        """Assert that the item is odd"""
        self.assertTrue( NUMBER %2==1, "Number should be odd")

Тестовое задание suite:

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(TestOdd())
    # I would like to have:
    # suite.addTest(TestOdd(1))
    # suite.addTest(TestOdd(2))
    # suite.addTest(TestOdd(3))
    # ...
    unittest.main()

Как я могу создать экземпляр TestOdd объект с аргументом - например, номер для проверки?

Обновление: согласно сообщению в блоге от 2011 года (опубликовано как ответ), нет встроенного механизма для параметризованных тестов. Я буду рад принять любые более чистые решения.

2 ответа

Решение

То же самое может быть достигнуто с помощью атрибутов класса.

class TestOdd1(unittest.TestCase):
    NUMBER=1
    def runTest(self):
        """Assert that the item is odd"""
        self.assertTrue( self.NUMBER % 2 == 1, "Number should be odd")

class TestOdd2(TestOdd1):
    NUMBER=2

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

Юнит-тестирование обнаружит их автоматически, поэтому нет необходимости создавать пакет.

Если вы хотите избежать использования TestCase для базового класса, вы можете использовать множественное наследование:

from unittest import TestCase, main

class TestOdd:
    def runTest(self):
        """Assert that the item is odd"""
        self.assertTrue( self.NUMBER % 2 == 1, "Number should be odd")

class TestOdd1(TestOdd, TestCase):
    NUMBER=1
class TestOdd2(TestOdd, TestCase):
    NUMBER=2

if __name__ == '__main__':
    main()

В соответствии с " модульным тестированием Python: параметризованные тесты", опубликованным в блоге Эли Бендерского:

Стандартная библиотека юнит-тестов Python великолепна, и я использую ее постоянно. Однако чего-то не хватает, это простой способ запуска параметризованных тестов. Другими словами, вы не можете легко передать аргументы в unittest.TestCase извне.

Решение Эли наследует unittest.TestCase в ParametrizedTestCase, Я не уверен в вопросах авторского права, поэтому я не буду копировать и вставлять код здесь.

Если есть какое-то лучшее решение, я буду рад принять его.

Я бы пошел по этому пути:

TestCase файл, содержащий саму тестовую логику:

import my_config
from unittest import TestCase

class TestOdd(unittest.TestCase):
    def runTest(self):
        """Assert that the item is odd"""
        self.assertTrue(int(my_config.options['number']) %2==1, "Number should be odd")

затем в TestSuite файл:

import argparse
import my_config
import TestCase

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-num', '--number', type=int, default=0)
    my_config.options = parser.parse_args()
    
    suite_case = unittest.TestLoader().loadTestsFromTestCase(TestCase)
    test_suite = unittest.TestSuite([suite_case])

    unittest.TextTestRunner(verbosity=1, failfast=True, buffer=False).run(test_suite)

my_config.py файл помощи:

options = {}

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

python3 -m unittest TestSuite.py --number=1
python3 -m unittest TestSuite.py --number=2
.
.
python3 -m unittest TestSuite.py --number=1000

Или вызов выполнения из командной строки может быть выполнен с помощью for цикл внутри сценария оболочки.

Другие вопросы по тегам