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 в ваших тестах, поэтому вам не нужно беспокоиться о его очистке.