Post on 01-Jul-2018
8/15/2019 Шаблоны тестирования xUnit.pdf
1/830
Шаблонытестирования xUnit
Рефакторингкода тестов
title indd 1title.indd 1 08 09 2008 10:39:1008.09.2008 10:39:10
8/15/2019 Шаблоны тестирования xUnit.pdf
2/830
Upper Saddle River, NJ • Boston • Indianapolis • San Francisco
New York • Toronto • Montreal • London • Munich • Paris • Madrid
Capetown • Sydney • Tokio • Singapore • Mexico City
ADDISONWESLEY
Gerard Meszaros
xUnitTest Patterns
Refactoring
Test Code
title indd 2title.indd 2 08 09 2008 10:39:1008.09.2008 10:39:10
8/15/2019 Шаблоны тестирования xUnit.pdf
3/830
Москва · СанктПетербург · Киев
2009
Джерард Месарош
Шаблонытестирования xUnit
Рефакторинг
кода тестов
title indd 3title.indd 3 08 09 2008 10:39:1108.09.2008 10:39:11
8/15/2019 Шаблоны тестирования xUnit.pdf
4/830
ББК 32.973.26018.2.75
М53УДК 681.3.07
Издательский дом ‘‘Вильямс”
Главный редактор С.Н. Тригуб
Зав. редакцией В.Р. Гинзбург
Перевод с английского и редакция О.А. Лещинского
По общим вопросам обращайтесь в Издательский дом ‘‘Вильямс’’ по адресу:info@williamspublishing.com, http://www.williamspublishing.com
Месарош, Джерард.
М53 Шаблоны тестирования xUnit: рефакторинг кода тестов. : Пер. с англ. М. : ООО
‘‘И.Д. Вильямс’’, 2009. 832 с. : ил. Парал. тит. англ.ISBN 9785845914484 (рус.)
В данной книге показано, как применять принципы разработки программного
обеспечения, в частности шаблоны проектирования, инкапсуляцию, исключение по
вторений и описательные имена, к написанию кода тестов. В части I рассматриваются
теоретические основы методов разработки тестов и описываются концепции шаблонов
и ‘‘запахов’’ тестов (признаков существующей проблемы). В частях II и III приводится
каталог шаблонов проектирования тестов, ‘‘запахов’’ и других средств обеспечения
большей прозрачности кода тестов. Кроме этого, в части III сделана попытка обобщить
и привести к единому знаменателю терминологию тестовых двойников и подставных
объектов, а также рассмотрены некоторые принципы их применения при проектирова
нии как тестов, так и самого программного обеспечения.Книга ориентирована на разработчиков программного обеспечения, практикующих гиб
кие процессы разработки. В основном здесь рассматриваются примеры для существующих
реализаций инфраструктуры xUnit, но затронуты и более новые инфраструктуры тестирова
ния на основе данных.
ББК 32.973.26018.2.75
Все названия программных продуктов являются зарегистрированными торговыми марками соответ
ствующих фирм.
Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в какой бы то ни
было форме и какими бы то ни было средствами, будь то электронные или механические, включая фо
токопирование и запись на магнитный носитель, если на это нет письменного разрешения издательства
AddisonWesley Publishing Company, Inc.
Authorized translation from the English language edition published by AddisonWesley, Copyright © 2007. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, elec
tronic or mechanical, including photocopying, recording or by any information storage retrieval system, without
permission from the publisher.
Russian language edition is published by Williams Publishing House according to the Agreement with R&I
Enterprises International, Copyright © 2009.
ISBN 9785845914484 (рус.) © Издательский дом ‘‘Вильямс’’, 2009
ISBN 9780131495050 (англ.) © Pearson Education, Inc., 2007
Стр. 4
8/15/2019 Шаблоны тестирования xUnit.pdf
5/830
Оглавление
Визуальное представление языка шаблонов 19
Предисловие 21
Пролог 23
Благодарности 29
Введение 31
Рефакторинг тестов 43
Часть I. Общая информация 59
Глава 1. Краткий обзор 61
Глава 2. Запахи тестов 67
Глава 3. Цели автоматизации 75
Глава 4. Философия автоматизации тестов 85
Глава 5. Принципы автоматизации тестирования 93
Глава 6. Стратегия автоматизации тестирования 103
Глава 7. Основы xUnit 127
Глава 8. Управление временной тестовой конфигурацией 137
Глава 9. Управление постоянными тестовыми конфигурациями 147
Глава 10. Проверка результатов 159
Глава 11. Использование тестовых двойников 175
Глава 12. Организация тестов 201
Глава 13. Тестирование с использованием баз данных 213
Глава 14. План эффективной автоматизации тестирования 221
Часть II. Запахи тестов 227
Глава 15. Запахи кода 229
Глава 16. Запахи поведения 263
Глава 17. Запахи проектов 295
Стр. 5
8/15/2019 Шаблоны тестирования xUnit.pdf
6/830
6 Оглавление
Часть III. Шаблоны 309
Глава 18. Шаблоны стратегии тестирования 311
Глава 19. Базовые шаблоны xUnit 377Глава 20. Шаблоны настройки тестовой конфигурации 433
Глава 21. Шаблоны проверки результатов 483
Глава 22. Шаблоны очистки тестовой конфигурации 517
Глава 23. Шаблоны тестовых двойников 537
Глава 24. Шаблоны организации тестов 603
Глава 25. Шаблоны баз данных 657
Глава 26. Шаблоны проектирования с учетом тестов 683
Глава 27. Шаблоны значений 717
Часть IV. Приложения 735
Приложение А. Рефакторинг тестов 737
Приложение Б. Терминология xUnit 743
Приложение В. Пакеты семейства xUnit 749
Приложение Г. Инструментарий 755
Приложение Д. Цели и принципы 759
Приложение Е. Запахи, псевдонимы и причины 763
Приложение Ж. Шаблоны, псевдонимы и варианты 767
Словарь терминов 784
Источники информации 813
Предметный указатель 827
Стр. 6
8/15/2019 Шаблоны тестирования xUnit.pdf
7/830
Содержание
Визуальное представление языка шаблонов 19
Предисловие 21
Пролог 23
Ценность самотестирующегося кода 23
Первый проект с использованием экстремального программирования 24Мотивация 26
Для кого предназначена эта книга 26
О фотографии на обложке 27 Ждем ваших отзывов! 27
Благодарности 29
Введение 31
Обратная связь 31Тестирование 31
Тестирование разработчиками 32
Автоматизированное тестирование 32Снижение чувствительности 34
Использование автоматизированных тестов 34Тест как спецификация 34
Разработка на основе тестов 35
Шаблоны 35Шаблоны, принципы и запахи 36
Исторические шаблоны и запахи 38
Ссылки на шаблоны и запахи 38Рефакторинг 39
Предположения 39
Терминология 40
Терминология тестирования 40Зависящая от языка терминология xUnit 41
Примеры кода 41Описание с помощью диаграмм 42
Ограничения 42
Рефакторинг тестов 43
Зачем нужен рефакторинг тестов 43Сложный тест 43
Стр. 7
8/15/2019 Шаблоны тестирования xUnit.pdf
8/830
8 Содержание
Очистка теста 44
Очистка логики верификации 44Очистка логики удаления тестовой конфигурации 47
Очистка кода инициализации 51Тест после всех модификаций 54Написание других тестов 55
Дальнейшее упрощение 56
Часть I. Общая информация 59
Глава 1. Краткий обзор 61
О чем идет речь в этой главе 61Самая простая рабочая стратегия автоматизации тестирования 61
Процесс разработки 62
Приемочные тесты 62Модульные тесты 63
Проектирование с учетом тестирования 64Организация тестов 65
Что дальше 65
Глава 2. Запахи тестов 67
О чем идет речь в этой главе 67
Введение в запахи тестов 67
Что такое запах теста 67Типы запахов тестов 68
Что делать с запахами 68
Каталог запахов 69Запахи проектов 69
Запахи поведения 70
Запахи кода 73Что дальше 74
Глава 3. Цели автоматизации 75
О чем идет речь в этой главе 75
Зачем нужны тесты 75
Экономическое обоснование автоматизации тестов 76Цели автоматизации тестов 77
Тесты должны способствовать повышению качества 77
Тесты должны способствовать пониманию принципов работытестируемой системы 78
Тесты должны снижать риск (не внося новых его источников) 79
Тесты должны легко запускаться 80Тесты должны быть простыми в написании и обслуживании 82
Тесты должны требовать минимального обслуживания
по мере развития системы 84Что дальше 84
Стр. 8
8/15/2019 Шаблоны тестирования xUnit.pdf
9/830
Содержание 9
Глава 4. Философия автоматизации тестов 85
О чем идет речь в этой главе 85
Почему важна философия 85Некоторые философские отличия 86
Тестировать до или после написания кода 86Тесты как примеры 86
Тест за тестом или все тесты сразу 87
Извне вовнутрь или изнутри наружу 88Проверка поведения или проверка состояния 89
Тестовая конфигурация для каждого теста или одна тестовая
конфигурация для всех тестов 90Почему возникают различия в философии 90
Философия автора 90Что дальше 91
Глава 5. Принципы автоматизации тестирования 93
О чем идет речь в этой главе 93Принципы 93
Принцип: сначала пишите тесты (Write the Tests First) 94
Принцип: проектируйте с учетом тестирования (Design for Testability) 94Принцип: сначала используйте “главный” вход (Use the Front Door First) 94
Принцип: доносите намерение (Communicate Intent) 95
Принцип: не модифицируйте тестируемую систему (Don’t Modify the SUT) 95Принцип: сохраняйте независимость тестов (Keep Tests Independent) 96
Принцип: изолируйте тестируемую систему (Isolate the SUT) 97
Принцип: минимизируйте пересечения тестов (Minimize Test Overlap) 98
Принцип: минимизируйте нетестируемый код (Minimize Untestable Code) 98Принцип: не вносите логику тестов в код продукта
(Keep Test Logic Out of Production Code) 99Принцип: проверяйте одно условие за тест (Verify One Condition per Test) 99
Принцип: тестируйте аспекты поотдельности (Test Concerns Separately) 101Принцип: обеспечьте адекватные усилия и ответственность
(Ensure Commensurate Effort and Responsibility) 101
Что дальше 101
Глава 6. Стратегия автоматизации тестирования 103
О чем идет речь в этой главе 103
Что значит “стратегический” 103
Какие тесты подвергать автоматизации 104Тесты функциональности 104
Кроссфункциональные тесты 106Инструментарий для автоматизации 107
Способы автоматизации тестирования и подходы к ней 108
Введение в xUnit 109Сильные стороны xUnit 110
Управление тестовыми конфигурациями 111Что такое тестовая конфигурация 111
Стр. 9
8/15/2019 Шаблоны тестирования xUnit.pdf
10/830
10 Содержание
Основные стратегии работы с тестовыми конфигурациями 112
Временная новая тестовая конфигурация 114Постоянная новая тестовая конфигурация 115
Стратегии на основе общей тестовой конфигурации 116Обеспечение простоты тестирования и взаимодействия с тестируемой системой 118
Тестируйте после, но не говорите, что вас не предупреждали 118
Готовый проект с учетом тестов — прыжок выше собственной головы 118
Возможность тестирования, обеспеченная тестами 118Контрольные точки и точки наблюдения 119
Стили взаимодействия и шаблоны тестирования 120Разделяй и тестируй 123
Что дальше 125
Глава 7. Основы xUnit 127
О чем идет речь в этой главе 127
Введение в xUnit 127
Общие функции 128Базовый минимум 128
Определение тестов 128
Что такое тестовая конфигурация 130Определение наборов тестов 130
Запуск тестов 131
Результаты выполнения теста 131Что происходит “под капотом” xUnit 133
Команды тестов 134
Объекты наборов тестов 134Реализации xUnit в процедурной парадигме 134
Что дальше 135
Глава 8. Управление временной тестовой конфигурацией 137
О чем идет речь в этой главе 137
Тестовые конфигурации 137Что такое тестовая конфигурация 137
Что такое новая тестовая конфигурация 139
Что такое временная новая тестовая конфигурация 139Создание новых тестовых конфигураций 140
Встроенная настройка тестовой конфигурации 140
Делегированная настройка тестовой конфигурации 141
Неявная настройка тестовой конфигурации 143Гибридная настройка тестовой конфигурации 145
Очистка временной новой тестовой конфигурации 145Что дальше 146
Глава 9. Управление постоянными тестовыми конфигурациями 147
О чем идет речь в этой главе 147
Управление постоянными новыми тестовыми конфигурациями 147
Что делает тестовую конфигурацию постоянной 148
Стр. 10
8/15/2019 Шаблоны тестирования xUnit.pdf
11/830
Содержание 11
Проблемы постоянных новых тестовых конфигураций 148
Очистка постоянных новых тестовых конфигураций 149Как избежать очистки 152
Решение проблемы медленных тестов 153Управление общими тестовыми конфигурациями 154
Доступ к общей тестовой конфигурации 154
Создание общей тестовой конфигурации 156
Что дальше 157
Глава 10. Проверка результатов 159
О чем идет речь в этой главе 159Создание самопроверяющихся тестов 159
Что проверять: состояние или поведение? 160
Проверка состояния 161Использование встроенных утверждений 162
Дельтаутверждения 163
Внешняя проверка результата 163Проверка поведения 164
Процедурная проверка поведения 164
Спецификация ожидаемого поведения 165Сокращение дублирования кода 166
Ожидаемый объект 166
Специальные утверждения 168Метод проверки с описанием результата 168
Параметризованный и управляемый данными тест 169
Как избежать условной логики в тестах 170Удаление операторов if 171
Исключение циклов 172 Другие способы 172
Разработка в порядке “извне вовнутрь” 172
Использование разработки на основе тестов для созданиявспомогательных методов теста 173
Расположение повторно используемой логики проверки 173
Что дальше 174
Глава 11. Использование тестовых двойников 175
О чем идет речь в этой главе 175
Что такое опосредованные ввод и вывод 175
Назначение информации об опосредованном вводе 176Назначение информации об опосредованном выводе 176
Управление опосредованным вводом 178Проверка опосредованного вывода 179
Тестирование с помощью двойников 183Типы тестовых двойников 183
Предоставление тестового двойника 189
Настройка тестового двойника 190Установка тестового двойника 192
Стр. 11
8/15/2019 Шаблоны тестирования xUnit.pdf
12/830
12 Содержание
Другие сферы применения тестовых двойников 197
Эндоскопическое тестирование 197Разработка на основе потребностей 198
Ускорение создания тестовой конфигурации 198Ускорение работы тестов 198
Другие аргументы 198
Что дальше 199
Глава 12. Организация тестов 201
О чем идет речь в этой главе 201
Базовые механизмы инструментария xUnit 201Размер тестовых методов 202
Тестовые методы и классы тестов 203
Класс теста для каждого класса 203Класс теста для каждой функции 203
Класс теста для каждой тестовой конфигурации 205
Выбор стратегии организации тестовых методов 205Соглашения об именовании тестов 206
Организация наборов тестов 206
Запуск групп тестов 208Запуск единственного теста 208
Повторное использование кода тестов 209
Наследование и повторное использование класса теста 210Организация тестовых файлов 211
Встроенные автотесты 211
Пакеты тестов 211Зависимости тестов 212
Что дальше 212
Глава 13. Тестирование с использованием баз данных 213
О чем идет речь в этой главе 213
Тестирование с использованием баз данных 213Причины тестирования с базами данных 214
Проблемы, связанные с базами данных 214
Тестирование без баз данных 215Тестирование базы данных 217
Тестирование хранимых процедур 217
Тестирование уровня доступа к данным 218
Обеспечение независимости разработчиков 219Тестирование с базами данных (опять!) 219
Что дальше 219
Глава 14. План эффективной автоматизации тестирования 221
О чем идет речь в этой главе 221Сложность автоматизации тестирования 221
План создания простых в обслуживании автоматизированных тестов 222
Выполните код на “счастливом маршруте” 223
Стр. 12
8/15/2019 Шаблоны тестирования xUnit.pdf
13/830
Содержание 13
Проверьте непосредственный вывод “счастливого маршрута” 223
Проверьте альтернативные ветви кода 224Проверьте поведение опосредованного вывода 225
Оптимизируйте запуск и обслуживание тестов 225Что дальше 226
Часть II. Запахи тестов 227
Глава 15. Запахи кода 229
Непонятный тест (Obscure Test) 230
Условная логика теста (Conditional Test Logic) 243
Сложный в тестировании код (HardtoTest Code) 251 Дублирование тестового кода (Test Code Duplication) 254
Логика теста в продукте (Test Logic in Production) 257
Глава 16. Запахи поведения 263
Рулетка утверждений (Assertion Roulette) 264
Нестабильный тест (Erratic Test) 267 “Хрупкий” тест (Fragile Test) 277
Частая отладка (Frequent Debuggin) 285
Ручное вмешательство (Manual Intervention) 287Медленные тесты (Slow Tests) 289
Глава 17. Запахи проектов 295
Тест с ошибками (Buggy Test) 296Разработчики не пишут тесты (Developers Not Writing Tests) 298
Высокая стоимость обслуживания тестов (High Test Maintenance Cost) 300Ошибки в продукте (Production Bugs) 303
Часть III. Шаблоны 309
Глава 18. Шаблоны стратегии тестирования 311
Записанный тест (Recorded Test) 312
Тест на основе сценария (Scripted Test) 319Управляемый данными тест (DataDriven Test) 322
Инфраструктура автоматизации тестов (Test Automation Framework) 332
Минимальная тестовая конфигурация (Minimal Fixture) 336Стандартная тестовая конфигурация (Standard Fixture) 338
Новая тестовая конфигурация (Fresh Fixture) 344Общая тестовая конфигурация (Shared Fixture) 350Манипуляция через “черный ход” (Back Door Manipulation) 359
Тест уровня (Layer Test) 368
Глава 19. Базовые шаблоны xUnit 377
Тестовый метод (Test Method) 378
Четырехфазный тест (FourPhase Test) 387Метод с утверждением (Assertion Method) 390
Стр. 13
8/15/2019 Шаблоны тестирования xUnit.pdf
14/830
14 Содержание
Сообщение для утверждения (Assertion Message) 398
Класс теста (Testcase Class) 401Программа запуска тестов (Test Runner) 405
Объект теста (Testcase Object) 410Объект набора тестов (Test Suite Object) 414Обнаружение тестов (Test Discovery) 420
Перечисление тестов (Test Enumeration) 425
Выбор тестов (Test Selection) 429
Глава 20. Шаблоны настройки тестовой конфигурации 433
Встроенная настройка (Inline Setup) 434 Делегированная настройка (Delegated Setup) 437
Метод создания (Creation Method) 441
Неявная настройка (Implicit Setup) 449Предварительно созданная тестовая конфигурация (Prebuilt Fixture) 454
“Ленивая” настройка (Lazy Setup) 460
Настройка тестовой конфигурации набора (Suite Fixture Setup) 465 Декоратор настройки (Setup Decorator) 471
Цепочки тестов (Chained Tests) 477
Глава 21. Шаблоны проверки результатов 483
Проверка состояния (State Verification) 484
Проверка поведения (Behavior Verification) 489
Специальное утверждение (Custom Assertion) 495 Дельтаутверждение (Delta Assertion) 505
Сторожевое утверждение (Guard Assertion) 510
Утверждение незаконченного теста (Unfinished Test Assertion) 514
Глава 22. Шаблоны очистки тестовой конфигурации 517
Очистка со сборкой мусора (GarbageCollected Teardown) 518 Автоматическая очистка (Automated Teardown) 521
Встроенная очистка (Inline Teardown) 527
Неявная очистка (Implicit Teardown) 533
Глава 23. Шаблоны тестовых двойников 537
Тестовый двойник (Test Double) 538
Тестовая заглушка (Test Stub) 544Тестовый агент (Test Spy) 552
Подставной объект (Mock Object) 558Поддельный объект (Fake Object) 565Настраиваемый тестовый двойник (Configurable Test Double) 571
Фиксированный тестовый двойник (HardCoded Test Double) 581Связанный с тестом подкласс (TestSpecific Subclass) 591
Глава 24. Шаблоны организации тестов 603
Именованный набор тестов (Named Test Suite) 604Вспомогательный метод теста (Test Utility Method) 610
Стр. 14
8/15/2019 Шаблоны тестирования xUnit.pdf
15/830
Содержание 15
Параметризованный тест (Parameterized Test) 618
Класс теста для каждого класса (Testcase Class per Class) 627Класс теста для каждой функции (Testcase Class per Feature) 633
Класс теста для каждой тестовой конфигурации (Testcase Class per Fixture) 639Суперкласс теста (Testcase Superclass) 646Вспомогательный класс теста (Test Helper) 651
Глава 25. Шаблоны баз данных 657
“Песочница” с базой данных (Database Sandbox) 658
Тест хранимой процедуры (Stored Procedure Test) 662
Очистка усечением таблиц (Table Truncation Teardown) 668Очистка откатом транзакции (Transaction Rollback Teardown) 675
Глава 26. Шаблоны проектирования с учетом тестов 683
Вставка зависимости (Dependency Injection) 684Поиск зависимости (Dependency Lookup) 692
Минимальный объект (Humble Object) 700
Ловушка для теста (Test Hook) 713
Глава 27. Шаблоны значений 717
Точное значение (Literal Value) 718
Вычисляемое значение (Derived Value) 722Сгенерированное значение (Generated Value) 726
Объектзаглушка (Dummy Object) 730
Часть IV. Приложения 735
Приложение А. Рефакторинг тестов 737
Приложение Б. Терминология xUnit 743
Приложение В. Пакеты семейства xUnit 749
Приложение Г. Инструментарий 755
Приложение Д. Цели и принципы 759
Приложение Е. Запахи, псевдонимы и причины 763
Приложение Ж. Шаблоны, псевдонимы и варианты 767
Словарь терминов 784
Источники информации 813Предметный указатель 827
Стр. 15
8/15/2019 Шаблоны тестирования xUnit.pdf
16/830
Стр. 16
8/15/2019 Шаблоны тестирования xUnit.pdf
17/830
8/15/2019 Шаблоны тестирования xUnit.pdf
18/830
Стр. 18
8/15/2019 Шаблоны тестирования xUnit.pdf
19/830
Визуальное представлениеязыка шаблонов
Запахи кода
Непонятный тест “Энергичный” тест
Тестоваяконфигурация
общего характера
Опосредованноетестирование
Таинственный гость
И другие!
Условная логика теста
Сложный в тестировании код
Дублиро ваниетестового кода
Логика теста в продукте
Нестабильныйтест
Неповторяемый тест Взаимодействующие
тесты
“Война” запуска тестовОптимизм поотношению к ресурсу
И другие!“Хрупкий” тест
“Хрупкая” тестовая конфигурация
Рулетка утверждений
Частая отладка
Ручное вмешательство
Медленные тесты
“Энергичный” тест
Цели проек та Цели написания тестов
Не навреди
Повторяемые тесты
Самопроверяющиеся
Выразительные тесты
Разделение интереса
Полностьюавтоматизированные
Жизнеспособный тест
Простой тест
Снижение риска
Тесты как страховочная сеть
Локализация дефектов
Простой в написании иобслуживании
Повышение качества
Тесты как документация
Тесты как спецификация
“Репеллент” для ошибок
Принципы автоматизации тестированияПишите сначала тесты
Изолируйтетестируемую систему
Не модифицируйтетестируемую систему
Минимизируйтепересечения тестов
Доносите намерение
Сначала используйтеглавный вход
Проверяйте одно условие за тест
Тестируйте аспекты отдельно
Сохраняйте независимостьтестов
Минимизируйтенетестируемый код
Не допускайте логику тестов в продукт
Обеспечьте соответственные усилия и ответственность
Цели автоматизации тестирования
Запахи проектов
Тесты с ошибками
Разработчики не пишут тесты
Высокая стоимостьобслуживания тестов
Ошибки в продукте
Запахи поведения
Цели, принципы и запахи
Схема визуального описания языка шаблона
Chapter N ame
SubCategory
SubCategory
Pattern 1 Al ternative P attern
from O ther ChapterPattern 2
Al terna tiv e
Pattern 1
Al terna tiv e
Pa ttern 2
Pattern
Pattern V ariation of P attern
leads to
v ariation of
used with
each other Variation describedseparately
C hapter N ame
Smell
Cause of Smell
Smell
Smell
Название главы
Подкатегория
Подкатегория
Шаблон 1 Альтернативныйшаблон из другойглавы
Шаблон 2
Альтернативный
шаблон 1
Шаблон
ШаблонВариант шаблона
приводит к
Вариант
используются
друг с другомВариант описываетсяотдельно
Название главы
Запах
Причина запаха
Альтернативный
шаблон 2
Запах
Запах
Стр. 19
8/15/2019 Шаблоны тестирования xUnit.pdf
20/830
20 Визуальное представление языка шаблонов
Создание тестового двойника
Объект
заглушка
Шаблоны тестовых двойников
Шаблоны настройки тестовой конфигурации
Точное
значение
Вычисляемое
значение
Сгенерированноезначение
Объект
заглушка
Шаблоны значений
Шаблоны проектирования с учетом тестов
Вставказависимости
Вставка метода установки
Вставка параметраВставка конструктора
Минимальный объект
Минимальный адаптер контейнера
Минимальный контроллер транзакций
Минимальный исполняемый файл
Минимальный диалог
Ловушка для теста
Поискзависимости
Фабрика объектов
Локатор служб
Связанный стестом подкласс
Замененныйединственный
экземпляр класса
Базовые шаблоны xUnit
Выбор тестов
Объект набора тестов
Выполнение теста
Программазапускатестов
Обнаружение тестов
Инфраструктура
автоматизации
тестов
Определение теста
Класс
теста
Метод с
утверждением
Сообщение для
утвержденияЧетырех
фазный тест
Перечисление тестов
Объект теста
Тестовый метод
Шаблоны баз данных
Тест
хранимой
процедуры
Очистка
откатом
транзакции
Очистка
усечением
таблиц
“Ленивая” очистка
“Песочница”
с базой данныхДельта
утверждение
Поддельная
база данных
Дельта
утверждение
Сторожевое
утверждение
СпециальноеутверждениеМетод проверки
Шаблоны проверки результата
Проверка
состояния
Проверка
поведения Методс утверждением
Проверка через
“черный ход”
Стратегия проверки
Стили методов с утверждением
Тест на основе
сценария
Управляемый
данными тест
Минимальнаятестовая конфигурация
Стандартнаятестовая конфигурация
Тест уровня
Манипуляциячерез
“черный ход” Немодифицируемая
тестовая конфигурация
Стратегия тестовой конфигурации
Шаблоны стратегии автоматизации тестирования
Записанный
тест
Стратегия автоматизации
Стратегия взаимодействия
с тестируемой системой
ПостояннаяВременная
Инфраструктура автоматизации тестов
Fresh Fixture Setup Создание общей тестовой конфигурации
“Ленивая”
настройка
Декоратор
настройки
Цепочки
тестов
Предварительносозданнаятестовая
конфигурация
Проверка результата
ДельтаутверждениеВспомогательный метод теста
Метод поиска
Доступ к общей тестовой конфигурации
Встроенная
настройка
Делегирован
ная настройка
Неявная
настройка
Метод
создания
Шаблоны очистки тестовой конфигурации
Постоянная новаятестовая конфигурация
Применимость
Встроенная очистка
Организация кода
Стратегия
Очистка
со сборкой
мусораШаблоны организации тестов
Суперкласстеста
Вспомогательныйкласс теста
Инкубаторобъектов
Класс
теста
Расположениевспомогательных
методов
Именованныйнабортестов
Структура класса теста
Класс теста для каждого классаКласс теста для каждойтестовой конфигурации
Класс теста для каждой функции
Повторное использованиекода тестов
Вспомогательный метод теста
Метод поиска
Специальное утверждение
Метод проверки
Метод создания
Параметризованный тест
Вспомогательныйкласс теста
Инкубатор объектов
Шаблоны
Новая тестоваяконфигурация
Обшая тестоваяконфигурация
Общая тестоваяконфигурация
Настройкатестовой
конфигурации
набора
Неявная очистка
Очистка
усечением
таблиц
Очистка
откатом
транзакции
Автомати
ческая
очистка
Поддельный
объект
Тестовая
заглушка
Тестовый
агент
Подставной
объект
Связанный стестом подкласс
Тестовый двойник
в виде подкласса
Тестовый
двойник
Настраиваемыйтестовыйдвойник
Фиксированныйтестовыйдвойник
Стр. 20
8/15/2019 Шаблоны тестирования xUnit.pdf
21/830
Предисловие
Если зайти на сайт junit.org, можно заметить мою цитату: ‘‘Никогда в отрасли разработки программного обеспечения столь многие не были так благодарны столь малому объему кода’’. Проект JUnit рассматривался как хоббипроект, который любому опытному разработчику под силу написать за выходные. Это так, но подобный взгляд отвлекает от главного. Важность проекта JUnit заключается в фундаментальном смещении фоку
са для многих разработчиков: тестирование превратилось в главную и основополагающую часть программирования. Многие предлагали такой подход к разработке и раньше,но именно JUnit сделал основной вклад в этот сдвиг.
Конечно, дело не только в JUnit. Идея была перенесена на большинство языков программирования. В результате целое семейство утилит стало называться xUnit, так как идея давно переросла реализацию для языка Java. (Конечно, все начиналось не с Java:Кент Бек написал этот код для языка Smalltalk значительно раньше.)
Утилиты xUnit, а также их философия, предоставляют огромные возможности коман дам разработчиков: мощные наборы регрессных тестов позволяют вносить значительныеизменения в код с минимальным риском, а при разработке на основе тестов на ходу пересматривать дизайн продукта.
Но эти возможности сопровождаются новыми проблемами и новыми методиками.Как и любой инструмент, семейство xUnit может использоваться неправильно. Опытныеразработчики накопили различные способы использования xUnit для эффективной организации тестов и данных. Как и на заре объектноориентированного программирования, большая часть знаний по практическому применению инструментария скрыта в го ловах опытных пользователей. Без этих ‘‘тайных знаний’’ очень тяжело использоватьвозможности пакета максимально эффективно.
Около двадцати лет назад была эта проблема была осознана сообществом объектноориентированной разработки. Решением проблемы стало описание ‘‘тайных знаний’’ ввиде шаблонов. Джерард Месарош был одним из пионеров этого процесса. Когда я началзнакомиться с шаблонами, Джерард был одним из лидеров, у которого мне довелось учиться. Как и многие в мире шаблонов, Джерард стал одним из апологетов технологии
экстремального программирования (eXtreme Programming), а значит, работал с утилитами xUnit с самого начала. Логично, что ему пришла в голову идея оформить свои знанияэксперта в виде шаблонов.
Мне понравился этот проект с того момента, когда я о нем услышал. (Мне пришлось провести спецоперацию по похищению данной книги у Боба Мартина, так как я хотел включить ее в свою серию.) Как и любая хорошая книга о шаблонах, онасодержит информацию, полезную новичкам в данной отрасли. Кроме того, книга
Стр. 21
8/15/2019 Шаблоны тестирования xUnit.pdf
22/830
22 Предисловие
может служить словарем и источником базовой информации для опытных разработчиков, которые пытаются передать свои знания коллегам. Широко известная книга‘‘банды четырех’’ Design Patterns (Приемы объектноориентированного проектирования, ‘‘Питер’’, 2005 г.) раскрыла секреты объектноориентированного проектирования. Предлагаемая вашему вниманию книга имеет такую же ценность с точки зренияприменения пакета xUnit.
Мартин Фаулер,редактор серии,
главный научный сотрудник, ThoughtWorks
Стр. 22
8/15/2019 Шаблоны тестирования xUnit.pdf
23/830
Пролог
Ценность самотестирующегося кода
В главе 4 книги Рефакторинг [Ref] Мартин Фаулер написал следующее.
Если обратить внимание на потраченное разработчиками время, можно заме
тить, что написание кода на самом деле составляет небольшую его часть. Некото
рое время тратится на постановку задачи, некоторое на проектирование,
но большая его часть уходит на отладку. Каждый читатель может вспомнить долгие часы отладки (часто до глубокой ночи). Любой разработчик может рассказать
историю об ошибке, исправление которой потребовало целого дня (или даже больше).
На самом деле для исправления ошибки много времени не нужно. А вот найти ошибку совсем другое дело. Не забывайте, что после исправления одной ошибки всегда
существует вероятность появления другой, которая остается незаметной очень
долго. И еще больше времени потребуется на ее обнаружение.
Некоторые приложения слишком сложны для тестирования вручную. Часто в таких случаях приходится писать тестовые программы.
В 1996 году автор участвовал в проекте, в котором его задача заключалась в создании
инфраструктуры событий, позволяющей клиентскому программному обеспечению регистрироваться в системе и получать уведомление, когда другое приложение генерировалосоответствующее событие (шаблон наблюдатель, Observer). Я не смог придумать лучшегоспособа тестирования инфраструктуры, чем создание макета клиентского программногообеспечения. Необходимо было проверить около двадцати различных сценариев, поэтому каждый сценарий был запрограммирован с использованием соответствующего числанаблюдателей, событий и генераторов событий. Поначалу за происходящим приходилосьследить, рассматривая вывод на консоль. Очень быстро такой способ контроля оказалсяслишком утомительным.
Определенная степень лени стимулировала поиск другого решения, связанного с контролем над процессом тестирования. Для каждого теста был создан словарь (Dictionary),
проиндексированный ожидаемыми событием и получателем и содержащий имя получателя в качестве значения. Как только конкретному получателю отправлялось уведомление о событии, получатель проверял словарь на наличие собственной записи с полученным событием. Если такая запись существовала, получатель ее удалял. Если запись несуществовала, получатель добавлял запись с сообщением об ошибке, указывающим на уведомление о неожиданном событии.
После запуска всех тестов тестовая программа просто просматривала словарь и выво дила непустые записи. В результате запуск всех тестов практически не был связан с накладными расходами. Тесты или успешно завершались без сообщений, или выводили
Стр. 23
8/15/2019 Шаблоны тестирования xUnit.pdf
24/830
24 Пролог
список сообщений о неудачах. Как потом оказалось, неожиданно для себя автор открылконцепции подставного объекта (Mock Object, с. 558) и инфраструктуры автоматизациитестов (Test Automation Framework, с. 332).
Первый проект с использованием экстремального программирования
В 1999 году автор был участником конференции OOPSLA, на которой распространя лась новая книга Кента Бека Экстремальное программирование [XPE]. К этому моменту автор уже применял итеративноинкрементный подход к разработке и уже понимал ценность автоматизированного модульного тестирования, хотя и не имел опыта его универсального применения. К Кенту Беку автор питал уважение еще со времен первой конференции PLoP (Pattern Languages of Programs) в 1994 году. Совокупность этих факторов убедила автора в желательности применения методологии экстремального программирования в проекте ClearStream Consulting. Почти сразу же после конференции OOPSLA
подвернулась возможность применить такой подход в реальном проекте это быловспомогательное приложение, взаимодействующее с существующей базой данных, но неимеющее собственного пользовательского интерфейса. При этом клиент был готов к применению нетрадиционных методик разработки.
С самого начала применялись все описанные в литературе принципы экстремального программирования, включая программирование в парах, общее владение кодом,а также разработку на основе тестов. Конечно, возникли и сложности при созданиитестов для некоторых аспектов поведения приложения, но для большей части кода тесты все же были написаны. После этого в процессе развития проекта стала наблюдатьсянастораживающая тенденция: реализация одних и тех же решений требовала все больше и больше времени.
После коротких объяснений разработчики стали записывать на каждой карточке за дачи время, которое требовалось для создания новых тестов, модификации существующих тестов и создания фактического кода. Очень быстро была выявлена и изолированаинтересная тенденция. Как оказалось, время создания новых тестов и написания кодаосталось практически неизменным. Но значительно возросло время модификации существующих тестов. Когда разработчик предложил поработать в паре, оказалось, что 90%рабочего времени ушло на модификацию существующих тестов, соответствующих относительно небольшому изменению в функциональности.
Анализ ошибок компиляции и неудачных результатов тестов при добавлении новойфункциональности показал, что многие тесты зависели от изменений в методах тестируемой системы. Это никого не удивило. А удивило то, что больше всего проблем возникало на этапе создания тестовой конфигурации и изменения не затрагивали основ
ную логику тестов.Это стало важным открытием, так как показало, что знания о создании объектовтестируемой системы были равномерно распределены между большинством тестов. Другими словами, тесты слишком много знали о не самых важных аспектах поведениятестируемой системы. Большинство затронутых тестов на самом деле не должны былизависеть от того, как создавались объекты в пределах тестовой конфигурации; их задачей была проверка правильности состояния объектов. При последующей проверкеоказалось, что многие тесты создавали одинаковые или почти одинаковые объекты наэтапе подготовки.
Стр. 24
8/15/2019 Шаблоны тестирования xUnit.pdf
25/830
Пролог 25
Очевидным решением проблемы было выделение этой логики в небольшой наборвспомогательных методов теста (Test Utility Method, с. 610). На тот момент существовалонесколько вариантов.
• Если несколько тестов требовали идентичных объектов, просто использовался метод, который возвращал необходимый объект. Такое решение теперь называется методом создания (Creation Method, с. 441).
• В некоторых тестах требовались различные значения атрибутов объекта. В такомслучае значение атрибута передавалось в качестве значения параметра для пара метризованного метода создания (Parameterized Creation Method).
• Некоторым тестам для нормальной работы требовался некорректно сформированный объект, чтобы убедиться в том, что тестируемая система откажется его обрабатывать. Генерация отдельного параметризованного метода создания (Parameterized Creation Method) для каждого атрибута излишне раздувала сигнатуру вспомо
гательного класса теста (Test Helper, с. 651), поэтому создавался нормальный объект, значение атрибутов которого модифицировалось с помощью единственногодефектного атрибута (One Bad Attribute).
Результатом стал набор тестов и методов, в дальнейшем превратившихся в первыешаблоны автоматизации тестов1.
Позднее, когда тесты стали завершаться неудачно изза отказа базы данных принимать объект с уже существующим идентификатором, был добавлен код для генерации уникального ключа. Этот фрагмент был назван анонимным методом создания (AnonymousCreation Method, с. 443), что указывало на дополнительную функциональность.
Идентификация проблемы, которая сейчас называется ‘‘хрупким’’ тестом (FragileTest, с. 277), была важным этапом проекта. Последующее определение шаблонов для ее
решения спасло проект от возможного неудачного завершения. Без этого открытия пришлось бы как минимум отказаться от уже написанных автоматизированных модульных тестов. В худшем случае тесты снизили бы производительность разработчиков настолько,что клиенты не получили бы необходимый результат. Но в итоге удалось выдать необхо димый продукт очень хорошего качества. Да, тестеры (функция тестирования иногда называется контролем качества; такое название является некорректным) находили ошибкив коде, так как некоторые тесты так и не были написаны. Но после того как были написаны отсутствующие тесты, внесение изменений для исправления обнаруженных ошибок практически не требовало усилий.
Тот проект показал, что автоматическое модульное тестирование и разработка на основетестов действительно работают. С тех пор данные методики используются постоянно.
Хотя разработанные практики и шаблоны применялись в последующих проектах,
приходилось сталкиваться с новыми проблемами и задачами. В каждом случае приходи лось слой за слоем откапывать корень проблемы и изобретать подходящие решения.Спустя некоторое время развития открытые техники добавлялись в набор подходов к автоматизированному модульному тестированию.
Часть из этих шаблонов была описана в выступлении для конференции XP2001.Обсуждение с коллегами на этой и последующих конференциях показало, что многие
1 Технически решение не является шаблоном, пока не будет найдено тремя независимыми группами разработчиков.
Стр. 25
8/15/2019 Шаблоны тестирования xUnit.pdf
26/830
26 Пролог
пользуются такими же или подобными методиками. В результате методы из ‘‘практик’’
превратились в ‘‘шаблоны’’ (повторяющееся решение повторяющейся проблемы).
Первое описание запахов теста (test smell) было опубликовано на той же конференции.
В основе понятия ‘‘запах теста’’ лежало понятие ‘‘запах кода’’, описанное в книге Рефакторинг [Ref]2.
Мотивация
Я глубоко убежден в важности автоматизированного модульного тестирования. Я раз
рабатывал программное обеспечение без этой технологии около двадцати лет. Инфра
структура xUnit и созданные на ее основе автоматизированные тесты являются одним из
заметных шагов в развитии отрасли разработки программного обеспечения. Каждый раз
очень неприятно наблюдать, как компания пытается применить автоматизированное мо
дульное тестирование, но терпит неудачу изза недостатка ключевой информации и не
обходимых навыков.Как консультант по разработке ПО в компании ClearStream Consulting я по долгу
службы сталкиваюсь с большим количеством проектов. Иногда клиент вызывает кон
сультанта в начале проекта, чтобы ‘‘все было правильно’’. Но чаще приходится подклю
чаться к проекту, когда он начинает свой полет под откос. В результате пришлось позна
комиться с ‘‘худшими практиками’’, лежащими в основе большинства запахов тестов.
Если повезло и меня позвали не слишком поздно, клиент сможет восстановиться после
совершенных ошибок. В противном случае клиенту придется выпутываться самому, счи
тая, что разработка на основе тестов и автоматизированное модульное тестирование дают
не очень хорошие результаты и клиент начнет распространять слухи об автоматизиро
ванном тестировании как о напрасной трате времени.
Оглядываясь в прошлое, приходится признаться, что все эти проблемы можно
было обойти, имея необходимые знания в нужный момент. Но как получить знание,
самостоятельно не совершив все ошибки? С точки зрения затраченного на изучение
новых технологий времени выгоднее всего пригласить специалиста, который уже об
ладает необходимыми знаниями. Ппосещение специализированных курсов или чте
ние книги является менее эффективной (хотя и более дешевой) альтернативой. На
деюсь, что, записав эти ошибки и рекомендованные методы их обхода, я смог по
мочь многим разработчикам.
Для кого предназначена эта книга
Эта книга написана в основном для разработчиков программного обеспечения
(программистов, проектировщиков и архитекторов), которые хотят научиться лучше пи
сать тесты, а также для руководителей и преподавателей, которые хотят понимать, что
делают разработчики и зачем им необходимо выделять время на повышение эффектив
ности этой деятельности. Основное внимание уделяется модульным тестам и приемоч
ным тестам, которые автоматизируются с помощью пакета xUnit. Кроме того, ряд шаб
лонов высокого уровня относится к тестам, автоматизированным на основе отличных от
2 В книге Мартина Фаулера [Ref] использовались термины ‘‘дурной запах’’ и ‘‘неприятный за
пах’’. Примеч. ред.
Стр. 26
8/15/2019 Шаблоны тестирования xUnit.pdf
27/830
Пролог 27
xUnit технологий. Рик Магридж и Уорд Каннингем написали отличную книгу по инфра
структуре Fit [FitB] и являются сторонниками многих из описанных здесь практик.
Скорее всего, разработчики захотят прочитать книгу от корки до корки, но справоч
ные главы лучше сначала просмотреть, а не вчитываться в каждое слово. Основное внимание нужно уделить общему представлению о существующих шаблонах и принципах их
функционирования. К конкретным шаблонам можно будет вернуться, когда в них воз
никнет необходимость. Обычно описание приводится в нескольких первых подразделах
(до раздела ‘‘Когда это использовать’’ включительно) того раздела, который посвященн
конкретному шаблону.
Руководителям и преподавателям рекомендуется прочитать часть I, ‘‘Общая инфор
мация’’, и, возможно, часть II, ‘‘Запахи тестов’’. Кроме того, желательно прочитать гла
ву 18, ‘‘Шаблоны стратегии тестирования’’, так как в ней описаны решения, смысл кото
рых руководители должны понимать, чтобы поддерживать разработчиков в использова
нии этих шаблонов. Как минимум руководители должны прочитать главу 3, ‘‘Цели
автоматизации’’.
О фотографии на обложке
На обложке каждой книги данной серии размещена фотография моста. Когда Мартин
Фаулер предложил включить книгу в свою серию, я задался вопросом: ‘‘Какой мост раз
местить на обложке?’’ Я подумал о способности тестирования предотвращать катастрофы
в работе программного обеспечения и о связи тестирования ПО с мостами. Сразу в голо
ву пришло несколько неудачных мостов, включая ‘‘Galloping Gertie’’ (мост Тэкома
Нэрроуз) и мост ‘‘Iron Workers Memorial Bridge’’ в Ванкувере (мост назван в память о ра
бочих, погибших при обрушении части конструкции).
После дальнейшего обдумывания мне показалось неоправданным утверждать, что
тестирование позволило бы избежать этих ошибок, поэтому мост был выбран, исходя из
личных побуждений. На обложке изображен мост ‘‘New River Gorge’’ в Западной Вирги
нии. Впервые мне довелось перейти его и проплыть под ним в конце 1980х годов. Архи
тектура моста также связана с содержимым этой книги: сложная арочная структура под
мостом в большинстве случаев скрыта от проезжающих по мосту. Дорога не имеет сты
ков, и ночью можно проехать мост, даже не заметив его тысячефутовой высоты. Хорошая
инфраструктура автоматизации тестов имеет то же свойство: писать тесты легко, так как
почти вся сложность скрыта под ‘‘дорожным полотном’’.
Ждем ваших отзывов!
Вы, читатель этой книги, и есть главный ее критик. Мы ценим ваше мнение и хотим
знать, что было сделано нами правильно, что можно было сделать лучше и что еще вы хо
тели бы увидеть изданным нами. Нам интересны любые ваши замечания в наш адрес.
Мы ждем ваших комментариев и надеемся на них. Вы можете прислать нам бумажное или
электронное письмо либо просто посетить наш сайт и оставить свои замечания там. Одним
словом, любым удобным для вас способом дайте нам знать, нравится ли вам эта книга, а также
выскажите свое мнение о том, как сделать наши книги более интересными для вас.
Стр. 27
8/15/2019 Шаблоны тестирования xUnit.pdf
28/830
28 Пролог
Отправляя письмо или сообщение, не забудьте указать название книги и ее авторов, а
также свой обратный адрес. Мы внимательно ознакомимся с вашим мнением и обяза
тельно учтем его при отборе и подготовке к изданию новых книг.
Наши электронные адреса:
Email: info@williamspublishing.com
WWW: http://www.williamspublishing.com
Наши почтовые адреса:
в России: 127055, г. Москва, ул. Лесная, д. 43, стр. 1
в Украине: 03150, Киев, а/я 152
Стр. 28
8/15/2019 Шаблоны тестирования xUnit.pdf
29/830
8/15/2019 Шаблоны тестирования xUnit.pdf
30/830
30 Благодарности
ла крайне сырой. Среди таких неофициальных рецензентов можно выделить Джавида Джамаи (Javid Jamae), Филипа Нельсона (Philip Nelson), Томаша Гаджевски (Tomasz Ga jewski), Джона Херста (John Hurst), Свена Гортса (Sven Gorts), Брэдли Ландиса (Bradley T.
Landis), Седрика Беста (Cеdric Beust), Джозефа Пелрине (Joseph Pelrine), СебастьянаБергмана (Sebastian Bergmann), Кевина Резерфорда (Kevin Rutherford), Скотта Амблера(Scott W. Ambler), Джей Би Рейнсбергера (J. B. Rainsberger), Оли Бая (Oli Bye), ДейлаЭмери (Dale Emery), Дейвида Нанна (David Nunn), Алекса Чаффи (Alex Chaffee), Буркхардта Хуфнагеля (Burkhardt Hufnagel), Йоханнеса Бродуолла (Johannes Brodwall), БретаПеттикорда (Bret Pettichord), Клинта Шанка (Clint Shank), Сунила Джоглекара (Sunil Joglekar), Рейчел Дейвис (Rachel Davies), Ната Прайса (Nat Pryce), Пола Ходжеттса (PaulHodgetts), Оуэна Роджерса (Owen Rogers), Амира Кольски (Amir Kolsky), Кевина Лоуренса (Kevin Lawrence), Алистэра Коуберна (Alistair Cockburn), Майкла Фезерса (MichaelFeathers) и Джо Шметцера (Joe Schmetzer). Отдельная благодарность выражается Нилу Норвицу (Neal Norwitz), Маркусу Гаэлли (Markus Gaelli), Стефани Дюкасс (Stephane Du
casse) и Стефану Райкхарту (Stefan Reichhart).Коекто отправлял мне электронные письма с описаниями часто применяемого шаб лона или специальной функции для используемого пакета xUnit. Большинство из них были вариациями уже документированных шаблонов. В книге они приводятся как псев донимы или варианты реализации. Было несколько более эзотерических шаблонов, которые не включены в книгу по соображениям объема. За это приношу извинения.
Многие из описанных в этой книге идей взяты из проектов, над которыми мне дове лось работать в компании ClearStream Consulting. Нам постоянно создавались предпосылки к поиску более оптимальных способов решения поставленных задач при наличииминимальных ресурсов. Такой подход дал начало многим методикам, описанным в данной книге. Коллегами автора по этому непростому процессу были Дженнита Андреа(Jennitta Andrea), Ральф Боне (Ralph Bohnet), Дейв Браат (Dave Braat), Рассел Брайант
(Russel Bryant), Грег Кук (Greg Cook), Джефф Харди (Geoff Hardy), Шон Смит (ShaunSmith) и Томас Таннахилл (Thomas Tannahill). Многие из них стали рецензентами ранних вариантов некоторых глав. Кроме того, Грег является автором большинства примеровкода в главе 25, а Ральф настроил хранилище CVS и автоматизированный процесс компиляции для сайта. Хотелось бы также поблагодарить руководство ClearStream Consultingза разрешение отказаться от консультаций и сконцентрироваться на написании книги иза разрешение на использование упражнений из двухдневного курса ‘‘Тестирование дляразработчиков’’ в качестве основы для большинства примеров кода. Итак, благодарности уходят Денису Клилланду (Denis Clelland) и Люку Макфарлану (Luke McFarlane)!
Несколько человек помогали мне работать над книгой, когда все становилось совсемсложно. Они всегда были готовы обсудить по телефону сложный вопрос. Особо хотелосьбы отметить Джошуа Кериевски (Joshua Kerievsky) и Мартина Фаулера.
Я выражаю искреннюю признательность Шону Смиту (Shaun Smith) за помощь и затехническую поддержку на начальных этапах работы над книгой. Он обеспечивал работу сайта, создал первые таблицы стилей CSS, научил меня применять Ruby, настроил Wikiресурс для обсуждения шаблонов и даже внес свой вклад в их наполнение, пока личные и рабочие факторы не заставили его отойти от писательской составляющейпроекта. Каждый раз, когда в описании полученного опыта говорит�