Экстремальное программирование. Разработка через тестирование | страница 64



self.runCount = 0

def testStarted(self):

self.runCount = self.runCount + 1

def summary(self):

return "%d run, 0 failed" % self.runCount


Теперь мы должны позаботиться о вызове этого нового метода:


TestCase

def run(self):

result = TestResult()

result.testStarted()

self.setUp()

method = getattr(self, self.name)

method()

self.tearDown()

return result


Мы точно так же могли бы преобразовать константу «0», обозначающую количество тестов, потерпевших неудачу, в переменную, как сделали это с переменной runCount, однако существующие тесты этого не требуют. Поэтому напишем новый тест:


TestCaseTest

def testFailedResult(self):

test = WasRun("testBrokenMethod")

result = test.run()

assert("1 run, 1 failed", result.summary)


Здесь:


WasRun

def testBrokenMethod(self):

raise Exception

Вызов тестового метода

Вызов метода setUp перед обращением к методу

Вызов метода tearDown после обращения к методу

Метод tearDown должен вызываться даже в случае неудачи теста

Выполнение нескольких тестов

Отчет о результатах

Строка журнала в классе WasRun

Отчет о неудачных тестах


Мы немедленно замечаем, что исключение, генерируемое в методе WasRun.testBrokenMethod(), не перехватывается. Нам хотелось бы перехватить это исключение и в отчете о результатах тестирования отметить, что тест потерпел неудачу. Добавим соответствующий пункт в список задач.


Подведем итог. Мы

• разработали поддельную реализацию и начали поэтапно делать ее реальной путем замены констант переменными;

• написали еще один тест;

• когда тест потерпел неудачу, написали еще один тест меньшего масштаба, чтобы обеспечить выполнение неудачного теста.

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() в случае, если тест потерпел неудачу.