Есть две важные вещи в пробной версии, связанные с этим вопросом.
Во-первых, тестовый метод не пройдет, если во время работы будет зарегистрирован сбой.Отложенные, которые являются мусором, собранным с результатом Отказа, приводят к регистрации Отказа.
Во-вторых, метод тестирования, который возвращает Отложенный, не пройдет, если Отложенный выстрелит с Отказом.что ни один из этих тестов не может пройти:
def test_logit(self):
defer.fail(Exception("oh no"))
def test_returnit(self):
return defer.fail(Exception("oh no"))
Это важно, потому что первый случай, когда Deferred является мусором, собираемым с результатом Failure, означает, что произошла ошибка, которую никто не обрабатывал.Это похоже на то, как Python сообщит о трассировке стека, если исключение достигнет верхнего уровня вашей программы.
Аналогично, второй случай - это сеть безопасности, предоставляемая пробной версией.Если синхронный метод теста вызывает исключение, тест не проходит.Поэтому, если метод пробного теста возвращает Отложенный, Отложенный должен иметь успешный результат для прохождения теста.
Однако существуют инструменты для работы с каждым из этих случаев.В конце концов, если у вас не может быть проходного теста для API, который возвращает Deferred, который иногда запускается с ошибкой, то вы никогда не сможете проверить свой код ошибки.Это была бы довольно печальная ситуация.:)
Итак, более полезным из двух инструментов для решения этой проблемы является TestCase.assertFailure
.Это помощник для тестов, которые хотят вернуть Deferred, который собирается сработать с ошибкой:
def test_returnit(self):
d = defer.fail(ValueError("6 is a bad value"))
return self.assertFailure(d, ValueError)
Этот тест пройдет, потому что d
сработает с ошибкой, заключающей ValueError.Если бы d
сработал с успешным результатом или с ошибкой, заключающей в себе какой-либо другой тип исключения, то тест все равно не прошел бы.
Далее, есть TestCase.flushLoggedErrors
.Это для тестирования API, который предполагается для регистрации ошибки.В конце концов, иногда вы действительно хотите сообщить администратору, что есть проблема.
def test_logit(self):
defer.fail(ValueError("6 is a bad value"))
gc.collect()
self.assertEquals(self.flushLoggedErrors(ValueError), 1)
Это позволяет вам проверять сбои, которые были зарегистрированы, чтобы убедиться, что ваш код регистрации работает правильно.Он также говорит пробной версии, что не стоит беспокоиться о вещах, которые вы сбросили, так что они больше не приведут к провалу теста.(Вызов gc.collect()
происходит потому, что ошибка не регистрируется до тех пор, пока Deferred не будет собран сборщиком мусора. На CPython он будет сразу же собран сборщиком мусора из-за поведения GC подсчета ссылок. Однако на Jython, PyPy или любом другомСреда выполнения Python без подсчета ссылок, вы не можете на это полагаться.)
Кроме того, поскольку сборка мусора может происходить практически в любое время, иногда вы можете обнаружить, что один из ваших тестов завершился неудачей, поскольку ошибка регистрируетсяa Deferred, созданный тестом ранее , является мусором, собранным во время выполнения более позднего теста.Это в значительной степени всегда означает, что ваш код обработки ошибок каким-то образом неполон - у вас отсутствует ошибка, или вы не сумели где-то соединить два Deferreds, или вы даете своему тестовому методу завершиться до того, как задача, которую он запустил, действительно завершится - носпособ сообщения об ошибке иногда затрудняет отслеживание кода, нарушающего работу.Опция Trial --force-gc
может помочь с этим.Это вызывает пробный запуск сборщика мусора между каждым методом тестирования.Это значительно замедлит ваши тесты, но должно привести к тому, что ошибка будет регистрироваться в сравнении с тестом, который фактически ее запускает, а не произвольным последующим тестом.