Заказ тестов Юнитест - PullRequest
       8

Заказ тестов Юнитест

39 голосов
/ 04 ноября 2010

Как я могу быть уверен в порядке методов unittest? Правильный ли алфавитный или цифровой префикс?

class TestFoo(TestCase):
    def test_1(self):
        ...
    def test_2(self):
        ...

или

class TestFoo(TestCase):
    def test_a(self):
        ...
    def test_b(self):
        ...

Ответы [ 17 ]

3 голосов
/ 31 марта 2017

Простой способ заказа тестов "unittest" заключается в использовании механизма init.d для присвоения им числовых имен:

def test_00_createEmptyObject(self):
    obj = MyObject()
    self.assertIsEqual(obj.property1, 0)
    self.assertIsEqual(obj.dict1, {})

def test_01_createObject(self):
    obj = MyObject(property1="hello", dict1={"pizza":"pepperoni"})
    self.assertIsEqual(obj.property1, "hello")
    self.assertIsDictEqual(obj.dict1, {"pizza":"pepperoni"})

def test_10_reverseProperty(self):
    obj = MyObject(property1="world")
    obj.reverseProperty1()
    self.assertIsEqual(obj.property1, "dlrow")

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

def make_myobject(self, property1, dict1):  # Must be specified by caller
    obj = MyObject(property1=property1, dict1=dict1)
    if property1:
        self.assertEqual(obj.property1, property1)
    else:
        self.assertEqual(obj.property1, 0)
    if dict1:
        self.assertDictEqual(obj.dict1, dict1)
    else:
        self.assertEqual(obj.dict1, {})
    return obj

def test_00_createEmptyObject(self):
    obj = self.make_object(None, None)

def test_01_createObject(self):
    obj = self.make_object("hello", {"pizza":"pepperoni"})

def test_10_reverseProperty(self):
    obj = self.make_object("world", None)
    obj.reverseProperty()
    self.assertEqual(obj.property1, "dlrow")
2 голосов
/ 06 ноября 2016

Я согласен с утверждением, что общий ответ "не делай этого" является плохим ответом.

У меня похожая ситуация, когда у меня один источник данных, и один тест уничтожит набор данных, что приведет к сбою других тестов.

Мое решение заключалось в использовании переменных среды операционной системы в моемBamboo server ...

(1) Проверка функциональности «очистка данных» начинается с цикла while, который проверяет состояние переменной среды «BLOCK_DATA_PURGE».Если переменная «BLOCK_DATA_PURGE» больше нуля, цикл запишет запись в журнал о том, что он спит 1 секунду.Когда «BLOCK_DATA_PURGE» имеет нулевое значение, выполнение переходит к проверке функциональности очистки.

(2) Любой модульный тест, для которого нужны данные в таблице, просто увеличивает значение «BLOCK_DATA_PURGE» в начале (в setup ()) и уменьшает ту же переменную в teardown ().

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

Сегодня я собираюсь расширить это, чтобы добавить больше функциональности, чтобы позволить некоторым тестам REQUIRE_DATA_PURGE.Это эффективно инвертирует описанный выше процесс, чтобы гарантировать, что эти тесты будут выполняться только после очистки данных для проверки восстановления данных.

1 голос
/ 04 марта 2012

См. Пример WidgetTestCase для http://docs.python.org/library/unittest.html#organizing-test-code, там написано, что

Каждый экземпляр класса теперь будет запускать один из тестовых методов _ * () с созданным self.widgetи уничтожается отдельно для каждого экземпляра.

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

1 голос
/ 04 ноября 2018

Я реализовал плагин nosedep для Nose , который добавляет поддержку тестовых зависимостей и приоритетов тестов.

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

Минимальный пример:

def test_a:
  pass

@depends(before=test_a)
def test_b:
  pass

Чтобы убедиться, что test_b всегда выполняется до test_a.

0 голосов
/ 28 декабря 2017

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

Однако, если вы все еще находите, что вам нужны тесты в определенном порядке (поскольку это целесообразно), вы можете попробовать проверитьответ на Python unittest.TestCase порядок выполнения .

0 голосов
/ 28 февраля 2019

Чтобы рандомизировать порядок тестовых методов, вы можете обезьянить пропатчить атрибут unittest.TestLoader.sortTestMethodsUsing

if __name__ == '__main__':
    import random
    unittest.TestLoader.sortTestMethodsUsing = lambda self, a, b: random.choice([1, 0, -1])
    unittest.main()

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

0 голосов
/ 10 ноября 2012

Вопреки сказанному здесь: - тесты должны выполняться изолированно (порядок не должен иметь значения для этого) И - их порядок важен, потому что они описывают, что делает система и как ее реализует разработчик.

IOW, каждый тест приносит вам информацию о системе и логике разработчика.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...