Unittest setUp / tearDown для нескольких тестов


119

Есть ли функция, которая запускается в начале / конце сценария тестов? Функции setUp и tearDown запускаются до / после каждого теста.

Обычно я хотел бы иметь это:

class TestSequenceFunctions(unittest.TestCase):

    def setUpScenario(self):
        start() #launched at the beginning, once

    def test_choice(self):
        element = random.choice(self.seq)
        self.assertTrue(element in self.seq)

    def test_sample(self):
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)

    def tearDownScenario(self):
        end() #launched at the end, once

На данный момент эти setUp и tearDown являются модульными тестами и распространяются во всех моих сценариях (содержащих множество тестов), один - первый тест, другой - последний.


6
Какая версия? Модуль unittest был расширен за счет включения модулей module_setup и module_teardown в Python 2.7.
S.Lott

3
2.7 также представлены методы классов setUpClass () и tearDownClass (), которые позволят вам иметь несколько классов в одном файле с их собственной настройкой и удалением для каждого набора.
Пер Фагрелл 05

Ответы:


132

Начиная с версии 2.7 (согласно документации ) вы получаете setUpClassи tearDownClassкоторые выполняются до и после запуска тестов в данном классе соответственно. В качестве альтернативы, если у вас есть группа из них в одном файле, вы можете использовать setUpModuleи tearDownModule( документация ).

В противном случае лучше всего будет создать собственный производный TestSuite и переопределить run(). Все остальные вызовы будут обрабатываться родителем, а run вызовет ваш код установки и удаления вокруг вызова родительского runметода.


72

У меня такой же сценарий, для меня методы setUpClass и tearDownClass отлично работают

import unittest

class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls._connection = createExpensiveConnectionObject()

    @classmethod
    def tearDownClass(cls):
        cls._connection.destroy()

6
Его следует обновить, чтобы он стал принятым ответом, потому что он показывает правильный пример, и эти функции ДОЛЖНЫ быть методами класса для работы, что не упоминается в принятом ответе.
NuclearPeon

1

Для python 2.5 и при работе с pydev это немного сложно. Похоже, что pydev не использует набор тестов, но находит все отдельные тестовые примеры и запускает их все отдельно.

Мое решение для этого заключалось в использовании такой переменной класса:

class TestCase(unittest.TestCase):
    runCount = 0

    def setUpClass(self):
        pass # overridden in actual testcases

    def run(self, result=None):
        if type(self).runCount == 0:
            self.setUpClass()

        super(TestCase, self).run(result)
        type(self).runCount += 1

С помощью этого трюка, когда вы наследуете от этого TestCase(а не от оригинала unittest.TestCase), вы также унаследуете значение runCount0. Затем в методе run runCountпроверяется и увеличивается значение дочернего тестового набора. Это оставляет runCountпеременную для этого класса равной 0.

Это означает, что setUpClassон будет запускаться только один раз для каждого класса, а не один раз для каждого экземпляра.

У меня еще нет tearDownClassметода, но я думаю, что с этим счетчиком можно что-то сделать.


0

Вот пример: 3 метода тестирования обращаются к общему ресурсу, который создается один раз, а не для каждого теста.

import unittest
import random

class TestSimulateLogistics(unittest.TestCase):

    shared_resource = None

    @classmethod
    def setUpClass(cls):
        cls.shared_resource = random.randint(1, 100)

    @classmethod
    def tearDownClass(cls):
        cls.shared_resource = None

    def test_1(self):
        print('test 1:', self.shared_resource)

    def test_2(self):
        print('test 2:', self.shared_resource)

    def test_3(self):
        print('test 3:', self.shared_resource)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.