Python unittest tearDownClass() для экземпляра, как его получить?

Мне нужен метод tearDownClass(cls) для этого экземпляра. Я имею в виду одно, где я могу ссылаться на себя (экземпляр), а не на cls (класс).
Этакий tearDownTestCase (self).

Я намерен очистить базу данных после ВСЕХ тестовых случаев.
tearDown (self) выполняется в конце каждого теста, и я не хочу его использовать.
tearDownClass(cls) выполняется один раз, когда ВСЕ тесты завершены, но он не содержит ссылку на себя, и мне нужно получить доступ к свойству себя (точнее, к функции).

Есть способ добиться этого?

Python 3.6

Пример реального сценария:

import unittest

'''
The real records saved in the database came from an external source (an API) so the ID is preassigned.
For the test I use everywhere a predefined fixed id, so the code result more clean.
'''

record_id = "TEST"

class RepositoryTest(unittest.TestCase):


    def setUp(self):
        # real initialization, reading connection string from config, database name, collection...
        self.repository = None
        # self._cleanup_record() # maybe here is executed too many unnecessary times

    def tearDown(self):
        # here is executed unnecessarily, because (where needed) the cleanup is eventually executed BEFORE the test (or in its beginning)
        self._cleanup_record()

    ### pseudo (desired) method ###
    def tearDownTestCase(self):
        self._cleanup_record()  

    def tearDownClass(cls):
        # self._cleanup_record()  # self is not available
        # rewrite the same code of initialization and _cleanup_record()
        # I want to a void (or simplify this)
        pass

    # this is 1 of N tests
    def test_save_record(self):

        # cleanup (because I don't know in which state the database is)
        self._cleanup_record()  # almost every test require this, so it can be done in setUp()

        # arrange
        record = self._create_record()

        # act
        self.repository.save_record(record)

        # assert
        saved_record = self._get_record()
        self.assertEquals(saved_record["my field"], record["my field"])



    # utility methods

    def _get_record(self):
        # use self.repository and return the record with id = record_id
        pass # return the record

    def _create_record(self):
        # use self.repository and create (and save) a record with id = record_id
        return None # return the saved record

    def _cleanup_record(self):
        # use self.repository and delete the record with id = record_id (if exists)
        pass

Выполнение очистки в методе tearDown () приводит к:

настроить

.test 1
уборка
тестовое задание
очистка (= избыточная)
,,,
.test N
уборка
тестовое задание
уборка

Вместо этого я хочу это:
(и это возможно, если метод tearDownX () будет выполнен после ВСЕХ испытаний)

настроить

(тест 1)
cleaup
тестовое задание
,,,
(тест N)
cleaup
тестовое задание

tearDownX (самостоятельно)
очистка (окончательная)

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


В качестве временного решения я повторил метод очистки в методе tearDownClass(cls), но я не доволен. В идеале я мог бы просто вызвать self._cleanup_record, но это невозможно, потому что tearDownClass - это метод класса.

Я надеюсь, что все это имеет смысл.

Спасибо,

Alessandro

1 ответ

Да, есть пара методов экземпляра setUp а также tearDown под unittest.TestCaseвыполняется до и после каждого теста соответственно.

Из документов:

setUp() Метод вызывается для подготовки тестового прибора. Это вызывается непосредственно перед вызовом тестового метода; Кроме как AssertionError или же SkipTestлюбое исключение, вызванное этим методом, будет считаться ошибкой, а не неудачей теста. Реализация по умолчанию ничего не делает.

tearDown() Метод вызывается сразу после вызова тестового метода и записи результата. Это вызывается, даже если тестовый метод вызвал исключение, поэтому реализация в подклассах может быть особенно осторожна при проверке внутреннего состояния. Любое исключение, кроме AssertionError или же SkipTestВозникновение этого метода будет считаться дополнительной ошибкой, а не провалом теста (таким образом, увеличивая общее количество зарегистрированных ошибок). Этот метод будет вызван только если setUp() успешно, независимо от результата метода испытаний. Реализация по умолчанию ничего не делает.

ОБНОВЛЕНИЕ (после комментариев)

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

В любом случае, поскольку вы не должны рассчитывать на порядок выполнения тестов, и ваши тесты не должны зависеть друг от друга, было бы разумно создать фиксатор db для каждого теста с setUp метод и очистить его tearDown метод после каждого теста.

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

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