Книга: Экстремальное программирование. Разработка через тестирование
22. Обработка неудачного теста
22. Обработка неудачного теста
Вызов тестового метода
Вызов метода setUp перед обращением к методу
Вызов метода tearDown после обращения к методу
Метод tearDown должен вызываться даже в случае неудачи теста
Выполнение нескольких тестов
Отчет о результатах
Строка журнала в классе WasRun
Отчет о неудачных тестах
Напишем еще один тест меньшего масштаба, демонстрирующий, что при обнаружении неудачного теста наша инфраструктура распечатывает на экране корректный результат:
TestCaseTest
def testFailedResultFormatting(self):
result = TestResult()
result.testStarted()
result.testFailed()
assert("1 run, 1 failed" == result.summary())
В данном тесте фигурируют два новых метода: testStarted() и testFailed(). Первый из них должен вызываться в начале работы теста, а второй – в случае, если тест не срабатывает. Тестовый метод testFailedResultFormatting() предполагает, что, если эти два метода вызываются в указанном порядке, отчет о результате тестирования должен выглядеть корректно. Если мы заставим этот тестовый метод работать, наша проблема сведется к тому, чтобы обеспечить вызов метода testStarted() в начале выполнения теста и вызов testFailed() в случае, если тест потерпел неудачу.
Чтобы реализовать функциональность методов testStarted() и testFailed(), воспользуемся двумя счетчиками: счетчиком запущенных тестов и счетчиком неудачных тестов:
TestResult
def __init__(self):
self.runCount = 0
self.errorCount = 0
def testFailed(self):
self.errorCount = self.errorCount + 1
Если счетчик будет работать корректно (мы должны были бы это протестировать, однако кофе, похоже, ударил мне в голову), отчет будет напечатан корректно:
TestResult
def summary(self):
return "%d run, %d failed" % (self.runCount, self.failureCount)
Теперь можно предположить, что, если обращение к методу testFailed() будет выполнено корректно, мы получим на экране желаемый результат. Но где следует вызвать этот метод? В обработчике исключения, перехваченного в процессе выполнения тестового метода:
TestCase
def run(self):
result = TestResult()
result.testStarted()
self.setUp()
try:
method = getattr(self, self.name)
method()
except:
result.testFailed()
self.tearDown()
return result
В этом коде присутствует одно тонкое место: если исключение возникает во время выполнения метода setUp(), оно не будет перехвачено. Это означает, что в определенной степени тесты зависят друг от друга. Однако прежде, чем менять код, мы должны написать еще один тест. (Я научил мою старшую дочку Бетани программировать в стиле TDD, когда ей было 12 лет. Это самый первый стиль программирования, с которым она познакомилась. Она не умеет программировать иначе и абсолютно уверена, что добавлять в программу новый функциональный код можно только в случае, если существует тест, который терпит неудачу. Однако более опытные программисты, как правило, вынуждены напоминать себе о том, что сначала необходимо писать тесты, а потом – код, заставляющий их выполняться.) Я оставляю этот следующий тест и его реализацию вам в качестве самостоятельного упражнения (мои пальцы опять устали):
Вызов тестового метода
Вызов метода setUp перед обращением к методу
Вызов метода tearDown после обращения к методу
Метод tearDown должен вызываться даже в случае неудачи теста
Выполнение нескольких тестов
Отчет о результатах
Строка журнала в классе WasRun
Отчет о неудачных тестах
Перехват и отчет об ошибках setUp
Далее мы сделаем так, чтобы наша инфраструктура смогла запустить несколько тестов подряд.
В данной главе мы
• обеспечили успешное выполнение нашего теста меньшего масштаба;
• заново приступили к реализации более крупного теста;
• обеспечили успешное выполнение крупного теста, воспользовавшись механизмом, реализованным для маленького теста;
• обратили внимание на потенциальную проблему, но вместо того, чтобы немедленно браться за ее решение, добавили соответствующую пометку в список задач.
- 11.8. ПРОЕКТИРОВАНИЕ КОМПЛЕКСНОГО ТЕСТА
- Разработка через тестирование и разработка с тестами
- Пример неудачного электронного сообщения
- Второстепенные объекты теста
- Методология проведения теста
- 6.2.4. Обработка произвольного файла термов
- 14. Обработка событий
- 6.3. Обработка символов
- 6.2. Обработка файлов термов
- Графический мир Армандо Теста
- На странице с результатами теста или калькулятором
- Акции протеста