TestSuite
class TestSuite:
def __init__(self):
self.tests = []
def add(self, test):
self.tests.append(test)
(В языке Python оператор [] создает пустую коллекцию.)
Однако с реализацией метода run() возникают проблемы. Мы хотим, чтобы результаты срабатывания всех тестов накапливались в едином объекте класса TestResult. Таким образом, мы можем написать следующий код:
TestSuite
def run(self):
result = TestResult()
for test in tests:
test.run(result)
return result
Здесь оператор цикла «for test in tests» выполняет итерации по всем элементам последовательности tests, присваивает их по одному переменной цикла test и запускает соответствующий тест. Однако шаблон «Компоновщик» (Composite) подразумевает, что набор объектов должен обладать точно таким же интерфейсом, каким обладает отдельный объект. Если мы передаем параметр методу TestCase.run(), значит, мы должны передавать точно такой же параметр методу TestSuite.run(). Можно использовать одну из трех альтернатив.
• Воспользоваться встроенным в язык Python механизмом параметров со значениями по умолчанию. К сожалению, значение параметра по умолчанию вычисляется во время компиляции, но не во время выполнения, а мы не хотим повторно использовать один и тот же объект TestResult.
• Разделить метод на две части – одна создает объект TestResult, а вторая выполняет тест, используя переданный ей объект TestResult. Я не могу придумать хороших имен для двух частей метода, а это означает, что данная стратегия не является самой лучшей.
• Создавать объекты TestResult в вызывающем коде.
Мы будем создавать объекты TestResult в вызывающем коде. Этот шаблон называется «Накапливающий параметр» (Collecting Parameter).
TestCaseTest
def testSuite(self):
suite = TestSuite()
suite.add(WasRun("testMethod"))
suite.add(WasRun("testBrokenMethod"))
result = TestResult()
suite.run(result)
assert("2 run, 1 failed" == result.summary())
При использовании данного подхода метод run() не возвращает никакого явного значения:
TestSuite
def run(self, result):
for test in tests:
test.run(result)
TestCase
def run(self, result):
result.testStarted()
self.setUp()
try:
method = getattr(self, self.name)
method()
except:
result.testFailed()
self.tearDown()
Теперь мы можем облагородить обращение к тестовым методам в конце файла:
suite = TestSuite()
suite.add(TestCaseTest("testTemplateMethod"))
suite.add(TestCaseTest("testResult"))
suite.add(TestCaseTest("testFailedResultFormatting"))
suite.add(TestCaseTest("testFailedResult"))
suite.add(TestCaseTest("testSuite"))
result = TestResult()
suite.run(result)
print(result.summary())
Метод tearDown должен вызываться даже в случае неудачи теста
Выполнение нескольких тестов
Перехват и отчет об ошибках setUp
Создать объект TestSuite автоматически на основе класса TestCase
Здесь слишком много повторяющегося кода, от которого можно избавиться, если обеспечить способ конструирования набора тестов автоматически, исходя из предоставленного класса TestCase.
Однако вначале восстановим корректное выполнение четырех не неудачных тестов (эти тесты используют старый интерфейс функции run() без аргументов):
TestCaseTest
def testTemplateMethod(self):
test = WasRun("testMethod")
result = TestResult()
test.run(result)
assert("setUp testMethod tearDown " == test.log)
def testResult(self):
test = WasRun("testMethod")
result = TestResult()
test.run(result)
assert("1 run, 0 failed" == result.summary())
def testFailedResult(self):
test = WasRun("testBrokenMethod")
result = TestResult()
test.run(result)
assert("1 run, 1 failed" == result.summary())
def testFailedResultFormatting(self):
result = TestResult()
result.testStarted()
result.testFailed()
assert("1 run, 1 failed" == result.summary())
Обратите внимание, что каждый из тестов создает экземпляр класса TestResult – эту операцию можно выполнить однократно внутри метода setUp(). Благодаря реализации этой идеи мы упростим тесты, однако сделаем их несколько более сложными в прочтении:
TestCaseTest
def setUp(self):
self.result = TestResult()
def testTemplateMethod(self):
test = WasRun("testMethod")
test.run(self.result)
assert("setUp testMethod tearDown " == test.log)
def testResult(self):
test = WasRun("testMethod")
test.run(self.result)
assert("1 run, 0 failed" == self.result.summary())
def testFailedResult(self):
test = WasRun("testBrokenMethod")
test.run(self.result)
assert("1 run, 1 failed" == self.result.summary())
def testFailedResultFormatting(self):
self.result.testStarted()
self.result.testFailed()
assert("1 run, 1 failed" == self.result.summary())
def testSuite(self):
suite = TestSuite()
suite.add(WasRun("testMethod"))
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии