Предоставление параметров в TestCase из пакета в python

из документации python(http://docs.python.org/library/unittest.html):

import unittest

class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

    def tearDown(self):
        self.widget.dispose()
        self.widget = None

    def test_default_size(self):
        self.assertEqual(self.widget.size(), (50,50),
                         'incorrect default size')

    def test_resize(self):
        self.widget.resize(100,150)
        self.assertEqual(self.widget.size(), (100,150),
                         'wrong size after resize')

вот, как вызвать те testcase:

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('test_default_size'))
    suite.addTest(WidgetTestCase('test_resize'))
    return suite

можно ли вставить параметр custom_parameter в WidgetTestCase, например:

class WidgetTestCase(unittest.TestCase):
    def setUp(self,custom_parameter):
        self.widget = Widget('The widget')
        self.custom_parameter=custom_parameter

?

5 ответов


что я сделал в модуле test_suite просто добавил

WidgetTestCase.CustomParameter="some_address"

самые простые решения являются лучшими :)


Я нашел способ сделать это, но это немного cludge.

в основном, то, что я делаю, это добавить в тестовый набор __init__ метод, который определяет параметр "по умолчанию" и __str__ Так что мы можем различать случаи:

class WidgetTestCase(unittest.TestCase):

    def __init__(self, methodName='runTest'):
        self.parameter = default_parameter
        unittest.TestCase.__init__(self, methodName)

    def __str__(self):
        ''' Override this so that we know which instance it is '''
        return "%s(%s) (%s)" % (self._testMethodName, self.currentTest, unittest._strclass(self.__class__))

затем в suite () я перебираю параметры теста, заменяя параметр по умолчанию одним конкретным для каждого теста:

def suite():
    suite = unittest.TestSuite()

    for test_parameter in test_parameters:
        loadedtests = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase)
        for t in loadedtests:
            t.parameter = test_parameter
        suite.addTests(loadedtests)

    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(OtherWidgetTestCases))
    return suite

здесь OtherWidgetTestCases - это тесты, которые не нужно параметризовать.

например I есть куча тестов на реальных данных, для которых набор тестов должен быть применен к каждому, но у меня также есть некоторые синтетические наборы данных, предназначенные для тестирования определенных крайних случаев, обычно не присутствующих в данных, и мне нужно только применить определенные тесты к ним, поэтому они получают свои собственные тесты в OtherWidgetTestCases.


это то, что было у меня на уме в последнее время. Да, это очень возможно сделать. Я назвал его тесты, но я думаю, что параметризованный может быть более точным. Я поставил доказательство концепции как gist здесь. Короче говоря, это мета-класс, который позволяет определить сценарий и запустить тесты против него кучу. С его помощью ваш пример может быть примерно таким:

class WidgetTestCase(unittest.TestCase):
    __metaclass__ = ScenarioMeta
    class widget_width(ScenerioTest):
        scenarios = [
            dict(widget_in=Widget("One Way"), expected_tuple=(50, 50)),
            dict(widget_in=Widget("Another Way"), expected_tuple=(100, 150))
        ]
        def __test__(self, widget_in, expected_tuple):
            self.assertEqual(widget_in.size, expected_tuple)

при запуске мета-класс записывает 2 отдельных теста, поэтому вывод было бы что-то вроде:

$ python myscerariotest.py -v
test_widget_width_0 (__main__.widget_width) ... ok
test_widget_width_1 (__main__.widget_width) ... ok


----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

Как вы можете видеть, сценариев преобразуются в тесты во время выполнения.

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

отметим, что с некоторым обманом тестовые случаи можно дать имена и даже вытащить из внешнего источника, такого как текстовый файл или база данных. Его еще не задокументировано, но некоторые раскопки в мета-классе должны заставить вас начать. На моем посту также есть дополнительная информация и примеры здесь.

редактировать

это уродливый хак, который я больше не поддерживаю. Реализация должна была быть выполнена как подкласс TestCase, а не как взломанный мета-класс. Жить и учить. Еще лучшим решением было бы использовать генераторы нос.


Я так не считаю, подпись для установки должна быть тем, что ожидает unittest, afaik, setUp автоматически вызывается в методе запуска testcase как setUp()... вы не сможете передать его, если не переопределите run для передачи в var, который вы хотите. Но я думаю, что то, что вы хотите, побеждает цель блок тестирование. Не пытайтесь использовать сухую философию с этим, каждый блок, который вы тестируете, должен быть частью класса или даже частью функции/метода.


Я не думаю, что это хорошая идея. Модульные тесты должны быть достаточно тщательными, чтобы вы тестировали все функции в своих случаях, поэтому передача разных параметров не требуется.

вы упоминаете, что вы проходите по адресу www-это почти наверняка не хорошая идея. Что произойдет, если вы попытаетесь запустить тесты на машине, где сетевое соединение не работает? Тесты должны быть:

  • автоматическое - они будут работать на всех машинах и платформах где поддерживается ваше приложение,без вмешательства пользователя. Они не должны полагаться на внешнюю среду, чтобы пройти. Это означает (среди прочего), что полагаться на правильно настроенное подключение к интернету-плохая идея. Вы можете обойти это, предоставив фиктивные данные. Вместо того, чтобы передавать URL-адрес ресурсу, абстрагируйте источник данных и передайте его в поток данных или что-то еще. Это особенно легко в python, так как вы можете использовать утку python для представления stream-like object (python часто использует "файловый" объект именно по этой причине!).

  • тщательный-ваши модульные тесты должны иметь 100% покрытие кода и охватывать все возможные ситуации. Вы хотите проверить свой код на нескольких сайтах? Вместо этого проверьте свой код со всеми возможными функциями, которые может включать сайт. Не зная больше о том, что делает ваше приложение, я не могу предложить много советов в этом вопросе.

теперь, похоже, ваши тесты будут сильно зависеть от данных. Существует множество инструментов, позволяющих определить наборы данных для модульных тестов и загрузить их в тесты. Например, проверьте тестовые приспособления python.

Я понимаю, что это не тот ответ, который вы ищете, но я думаю, что вы будете иметь больше радости в долгосрочной перспективе, если вы будете следовать этим принципам.