1. Учебный Центр Luxoft www.luxoft.ru/edu
Разработка через тестирование
(Test Driven Development)
Development)
EKrivosheev@luxoft.com
О вашем инструкторе
Имя
Статусы
Контакты
1-2
Рабочие материалы
Презентация
Рабочая среда на ПК
1-3
1
2. Учебный Центр Luxoft www.luxoft.ru/edu
Цели курса...
курса...
По окончании данного курса
слушатели:
получат общее понятие о целях и
задачах тестирования
освоят технологии модульного
тестирования
научатся применять шаблоны при
разработке модульных тестов
1-4
Цели курса…
курса…
По окончании данного курса
слушатели:
ознакомятся с синтаксисом и
приобретут опыт практического
использования одной из сред
тестирования семейства xUnit
(JUnit/NUnit)
освоят практику разработки через
тестирование
1-5
...Цели курса
...Цели
По окончании данного курса
слушатели:
научаться применять шаблоны TDD
получат практический опыт
разработки приложения с
использованием TDD
1-6
2
3. Учебный Центр Luxoft www.luxoft.ru/edu
Необходимая подготовка
Слушатели должны:
иметь опыт разработки на одном из
языков программирования: Java/C#
1-7
Знакомство
Напишите свое имя на пирамидке,
пожалуйста
Ваш опыт разработки на Java/С#
Ваш опыт работы с JUnit
Ваш опыт разработки по TDD
1-8
Расписание
День 1 Модуль 0: Введение
Модуль 1: Тестирование в разработке
ПО
Модуль 2: Библиотека модульного
тестирования JUnit
День 2 Модуль 3: Test-driven development
Модуль 4: TDD Workshop
1-9
3
4. Учебный Центр Luxoft www.luxoft.ru/edu
Общие рекомендации
Пожалуйста,
Отключите телефоны
Задавая вопросы, старайтесь
придерживаться темы обсуждения
Если у вас возникли вопросы, не
относящиеся к теме, пометьте их, и
инструктор будет рад ответить при
подходящем случае
1-10
Организация обучения
Время начала и конца занятий
Перерывы
Питание
1-11
Вопросы и ответы
1-12
4
5. Учебный Центр Luxoft www.luxoft.ru/edu
План курса
Модуль 1: Модульное тестирование
Тестирование как способ обеспечения
качества продукта
Уровни тестирования
Цели и задачи модульного тестирования
Покрытие кода
Унаследованный код
Организационные аспекты тестирования
2-13
Тестирование – способ
обеспечения качества продукта
Качество ПО
Качество программного продукта
характеризуется набором свойств,
определяющих, насколько продукт "хорош"
с точки зрения заинтересованных сторон
2-14
Тестирование – способ
обеспечения качества продукта
Качество ПО
Заинтересованными сторонами являются:
заказчик продукта
спонсор
конечный пользователь
разработчики
тестировщики продукта
инженеры поддержки
сотрудники отделов маркетинга, обучения и
продаж
2-15
5
6. Учебный Центр Luxoft www.luxoft.ru/edu
Тестирование – способ
обеспечения качества продукта
Качество ПО
Каждый из участников может иметь
различное представление о продукте и о
том, насколько он хорош или плох (то есть
о том, насколько высоко качество
продукта)
2-16
Тестирование – способ
обеспечения качества продукта
Качество ПО
Таким образом, постановка задачи
обеспечения качества продукта
выливается в задачи:
определения заинтересованных лиц
их критериев качества
нахождения оптимального решения,
удовлетворяющего этим критериям
2-17
Тестирование – способ
обеспечения качества продукта
Тестирование: общие понятия
Тестирование является одним из
наиболее устоявшихся способов
обеспечения качества разработки
программного обеспечения
Оно является одним из эффективных
средств современной системы обеспечения
качества программного продукта
Верификация и валидация ПО
2-18
6
7. Учебный Центр Luxoft www.luxoft.ru/edu
Тестирование – способ
обеспечения качества продукта
Тестирование: общие понятия
С технической точки зрения,
тестирование заключается в:
выполнении приложения на некотором
множестве исходных данных
сверке получаемых результатов с заранее
известными (эталонными) с целью
установить соответствие различных
свойств и характеристик приложения
заказанным свойствам
2-19
Тестирование – способ
обеспечения качества продукта
Тестирование: общие понятия
Тестирование является одной из
основных фаз разработки программного
продукта (наряду с Дизайном приложения
и Разработкой кода)
Оно характеризуется достаточно большим
вкладом в суммарную трудоемкость
разработки продукта
2-20
Тестирование – способ
обеспечения качества продукта
Эффективность автоматизации
Широко известна оценка распределения
трудоемкости между фазами создания
программного продукта: 40%-20%-40%*
(см. рисунок)
Оценка распределения трудоемкости и
стоимости исправления ошибки
*Котляров В.П., Основы тестирования программного обеспечения
2-21
7
8. Учебный Центр Luxoft www.luxoft.ru/edu
Тестирование – способ
обеспечения качества продукта
Эффективность автоматизации
Следовательно, наибольший эффект в
снижении трудоемкости может быть
получен прежде всего на фазах Design и
Testing
А значит и основные вложения в
автоматизацию или генерацию кода
следует осуществлять, прежде всего, на
этих фазах
2-22
Тестирование – способ
обеспечения качества продукта
Эффективность автоматизации
Как видно из графика, стоимость
исправления ошибок минимальна на
стадиях дизайна и разработки
Т.е. было бы неплохо обнаруживать
большую часть ошибок до начала фазы
тестирования
2-23
Тестирование – способ
обеспечения качества продукта
Эффективность автоматизации
Однако технологии автоматизированного
тестирования дизайна (верификации
требований и спецификаций) только
начинают появляться
Трейсинг (дизайна и требований)
В то же время, автоматизированное
тестирование кода является широко
распространенной практикой
2-24
8
9. Учебный Центр Luxoft www.luxoft.ru/edu
Тестирование – способ
обеспечения качества продукта
Эффективность автоматизации
Таким образом, процесс тестирования
затрагивает все фазы производства ПО,
однако не на всех фазах он может быть
успешно автоматизирован
2-25
Тестирование – способ
обеспечения качества продукта
Уровни тестирования
Разработка системы, как правило, идет на
различных уровнях:
вначале разрабатывается концепция системы,
системные требования
затем архитектура системы, ее разбиение на
модули
затем разрабатываются отдельные модули
Процесс верификации также разбивается на
отдельные уровни
2-26
План курса
Модуль 1: Модульные тесты
Тестирование как способ обеспечения
качества продукта
Уровни тестирования
Цели и задачи модульного тестирования
Покрытие кода
Унаследованный код
Организационные аспекты тестирования
2-27
9
10. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни тестирования
Уровни тестирования
системное тестирование, в ходе
которого тестируется система в целом;
интеграционное тестирование, в ходе
которого тестируются группы
взаимодействующих модулей и компонент
системы;
модульное тестирование, в ходе
которого тестируются отдельные
компоненты
2-28
Уровни тестирования
Системное тестирование
Системное тестирование
(System Testing):
Основной задачей системного
тестирования является проверка как
функциональных, так и нефункциональных
требований в системе в целом
2-29
Уровни тестирования
Системное тестирование
В ходе системного тестирования
выявляются следующие дефекты:
неверное использование ресурсов системы
непредусмотренные комбинации данных
пользовательского уровня
несовместимость с окружением
непредусмотренные сценарии использования
отсутствующая или неверная
функциональность
неудобство использования и т.д.
2-30
10
11. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни тестирования
Системное тестирование
Для минимизации рисков, связанных с
особенностями поведения в системы в той
или иной среде, во время тестирования
рекомендуется использовать окружение
максимально приближенное к тому, на
которое будет установлен продукт после
выдачи
2-31
Уровни тестирования
Интеграционное тестирование
Интеграционное тестирование
(Integration Testing):
Интеграционное тестирование
предназначено для проверки связи между
компонентами, а также взаимодействия с
различными частями системы
(операционной системой, оборудованием
либо связи между различными системами)
2-32
Уровни тестирования
Интеграционное тестирование
Интеграционное тестирование так же
может проводиться на различных уровнях:
Компонентный: проверяется
взаимодействие между компонентами
системы после проведения компонентного
(модульного) тестирования
Системный: проверяется взаимодействие
между разными системами после
проведения системного тестирования
2-33
11
12. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни тестирования
Модульное тестирование
Компонентное или Модульное
тестирование
(Component or Unit Testing):
Модульное тестирование проверяет
функциональность и ищет дефекты в
частях приложения, которые доступны и
могут быть протестированы по
отдельности (модули программ, объекты,
классы, функции и т.д.)
2-34
Уровни тестирования
Модульное тестирование
Обычно компонентное (модульное)
тестирование проводится вызывая код,
который необходимо проверить (при
поддержке среды разработки)
Все найденные дефекты, как правило,
исправляются в коде без формального их
описания в системе управления ошибками
2-35
План курса
Модуль 1: Модульные тесты
Тестирование как способ обеспечения
качества продукта
Уровни тестирования
Цели и задачи модульного
тестирования
Покрытие кода
Унаследованный код
Организационные аспекты тестирования
2-36
12
13. Учебный Центр Luxoft www.luxoft.ru/edu
Цели и задачи модульного
тестирования
Модульное тестирование
Каждая сложная программная система
состоит из отдельных частей - модулей,
выполняющих ту или иную функцию в
составе системы
Для того, чтобы удостовериться в
корректной работе всей системы,
необходимо вначале протестировать
каждый модуль системы по отдельности
2-37
Цели и задачи модульного
тестирования
Модульное тестирование
В случае возникновения проблем при
тестировании системы в целом это
позволяет проще выявить модули,
вызвавшие проблему, и устранить
соответствующие дефекты в них
Такое тестирование модулей по
отдельности получило называние
модульного тестирования
(unit testing) 2-38
Цели и задачи модульного
тестирования
Определения
Тестовый драйвер (среда, фреймворк)
– система, позволяющая выполнять и
контролировать результат выполнения
тестов. Как правило, позволяет также
корректировать входные данные, включает
в себя систему обработки исключительных
ситуаций и восстановления, средства
параметризации тестов и управления
данными
2-39
13
14. Учебный Центр Luxoft www.luxoft.ru/edu
Цели и задачи модульного
тестирования
Определения
Заглушка – объект, предназначенный для
симуляции поведения реального объекта
во время тестирования
Тест-план – представляет собой документ,
в котором перечислены либо все тестовые
примеры, необходимые для тестирования
системы, либо часть тестовых примеров,
объединенных по определенному признаку
2-40
Цели и задачи модульного
тестирования
Определения
Тест-требования – содержат описание
требований по проверке всех основных
функций системы
Для каждого модуля, подвергаемого
тестированию, разрабатывается тестовое
окружение, включающее в себя драйвер и
заглушки, готовятся тест-требования и
тест-планы, описывающие конкретные
тестовые примеры 2-41
Цели и задачи модульного
тестирования
Цели модульного тестирования
Основная цель модульного тестирования -
удостовериться в соответствии
требованиям каждого отдельного модуля
системы перед тем, как будет произведена
его интеграция в состав системы
2-42
14
15. Учебный Центр Luxoft www.luxoft.ru/edu
Цели и задачи модульного
тестирования
Задачи модульного тестирования
В ходе модульного тестирования решаются
следующие основные задачи:
Поиск и документирование несоответствий
требованиям
Поддержка разработки и рефакторинга
низкоуровневой архитектуры системы и
межмодульного взаимодействия
Поддержка рефакторинга модулей
Поддержка устранения дефектов и отладки2-43
Цели и задачи модульного
тестирования
Задачи модульного тестирования
Рефакторинг – процесс полного или
частичного преобразования внутренней
структуры программы при сохранении её
внешнего поведения. В его основе лежит
последовательность небольших
эквивалентных (т.е., сохраняющих
поведение) преобразований.
2-44
Цели и задачи модульного
тестирования
Задачи модульного тестирования
Поиск и документирование
несоответствий требованиям -
классическая задача тестирования,
включающая в себя не только разработку
тестового окружения и тестовых примеров,
но и выполнение тестов,
протоколирование результатов
выполнения, составление отчетов о
проблемах
2-45
15
16. Учебный Центр Luxoft www.luxoft.ru/edu
Цели и задачи модульного
тестирования
Задачи модульного тестирования
Поддержка разработки и
рефакторинга низкоуровневой
архитектуры системы и
межмодульного взаимодействия –
модульные тесты помогают выявить
проблемы в дизайне системы и
нелогичные или запутанные механизмы
работы с модулем
2-46
Цели и задачи модульного
тестирования
Задачи модульного тестирования
Поддержка устранения дефектов и
отладки сопряжена с обратной связью,
которую получают разработчики от
тестировщиков в виде отчетов о
проблемах
2-47
Цели и задачи модульного
тестирования
Задачи модульного тестирования
Подробные отчеты о проблемах,
составленные на этапе модульного
тестирования, позволяют локализовать и
устранить многие дефекты в программной
системе на ранних стадиях ее разработки
или разработки ее новой
функциональности
2-48
16
17. Учебный Центр Luxoft www.luxoft.ru/edu
Определение модуля
Проблемы определения модуля
В силу того, что модули, подвергаемые
тестированию, обычно невелики по
размеру, модульное тестирование
считается наиболее простым (хотя и
достаточно трудоемким) этапом
тестирования системы
Однако, несмотря на внешнюю простоту, с
модульным тестированием сопряжены две
проблемы:
2-49
Определение модуля
Проблемы определения модуля
не существует единых принципов
определения того, что в точности является
отдельным модулем
трактовка понятия модульного
тестирования - понимается ли под ним
обособленное тестирование модуля, работа
которого поддерживается только тестовым
окружением, или речь идет о проверке
корректности работы модуля в составе уже
разработанной системы
2-50
Определение модуля
Традиционное определение
Традиционное определение модуля с точки
зрения его тестирования:
модуль - это компонент минимального
размера, который может быть независимо
протестирован в ходе верификации
программной системы
В реальности часто возникают проблемы с
тем, что считать модулем
2-51
17
18. Учебный Центр Luxoft www.luxoft.ru/edu
Определение модуля
Альтернативные определения
Существует несколько подходов к данному
вопросу:
модуль - это часть программного кода,
выполняющая одну функцию с точки
зрения функциональных требований
модуль - это программный модуль, т.е.
минимальный компилируемый элемент
программной системы
2-52
Определение модуля
Альтернативные определения
модуль - это задача в списке задач
проекта (с точки зрения его менеджера)
модуль - это участок кода, который может
уместиться на одном экране или одном
листе бумаги
модуль - это один класс или их
множество с единым интерфейсом
модуль - это одна функция или метод
2-53
Определение модуля
Границы модуля
Обычно за тестируемый модуль
принимается либо программный модуль
(единица компиляции) в случае, если
система разрабатывается на процедурном
языке, или класс, если система
разрабатывается на объектно-
ориентированном языке
2-54
18
19. Учебный Центр Luxoft www.luxoft.ru/edu
Определение модуля
Границы модуля
В случае систем, написанных на
процедурных языках, процесс
тестирования модуля происходит
достаточно просто – для каждого модуля
разрабатывается:
тестовый драйвер, вызывающий функции
модуля и собирающий результаты их
работы
набор заглушек, которые имитируют
поведение функций, содержащихся в
других модулях
2-55
Определение модуля
Границы модуля
При тестировании объектно-
ориентированных систем существует ряд
особенностей, прежде всего вызванных
инкапсуляцией данных и методов в
классах (декомпозиция класса нарушит
принцип инкапсуляции, согласно которому
объекты каждого класса должны вести
себя как единое целое с точки зрения
других объектов)
2-56
Определение модуля
Границы модуля
Кроме того, более мелкое деление классов
и использование отдельных методов в
качестве тестируемых модулей
нецелесообразно, поскольку для
тестирования каждого метода потребуется
разработка тестового окружения,
сравнимого по сложности с уже
написанным программным кодом класса
2-57
19
20. Учебный Центр Luxoft www.luxoft.ru/edu
Определение модуля
Компонентное тестирование
Процесс тестирования классов как модулей
иногда называют компонентным
тестированием
В ходе такого тестирования проверяется
взаимодействие методов внутри класса и
правильность доступа методов к
внутренним данным класса
2-58
Определение модуля
Компонентное тестирование
На данном этапе возможно обнаружение
не только стандартных дефектов
(связанных с выходами за границы
диапазона или неверно реализованными
требованиями), но и специфических
дефектов объектно-ориентированного
программного обеспечения
2-59
Определение модуля
Специфические дефекты ООП
Такими дефектами являются:
дефекты инкапсуляции, в результате
которых, например, сокрытые данные
класса оказываются недоступными для
соответствующих публичных методов
дефекты наследования, при наличии
которых схема наследования блокирует
важные данные или методы от классов-
потомков
2-60
20
21. Учебный Центр Luxoft www.luxoft.ru/edu
Определение модуля
Специфические дефекты ООП
дефекты полиморфизма, при которых
полиморфное поведение класса
оказывается распространенным не на все
возможные классы
дефекты инстанцирования, при
которых во вновь создаваемых объектах
класса не устанавливаются корректные
значения по умолчанию параметров и
внутренних данных класса
2-61
Определение модуля
Проблемы тестирования в ООП
Однако, выбор класса в качестве
тестируемого модуля имеет и ряд
сопряженных проблем:
Определение степени полноты
тестирования класса
Протоколирование состояний объектов и
их изменений
Тестирование изменений
2-62
Определение модуля
Проблемы тестирования в ООП
Определение степени полноты тестирования
класса:
В том случае, если в качестве
тестируемого модуля выбран класс, не
совсем ясно, как определять степень
полноты его тестирования
Классический критерий полноты покрытия:
тесты можно считать полными, если
выполнены все структурные элементы всех
методов, как публичных, так и скрытых 2-63
21
22. Учебный Центр Luxoft www.luxoft.ru/edu
Определение модуля
Проблемы тестирования в ООП
Однако существует альтернативный
подход к тестированию класса: все
публичные методы должны предоставлять
пользователю данного класса
согласованную схему работы
В этом случае достаточно проверить
типичные корректные и некорректные
сценарии работы с данным классом
2-64
Определение модуля
Проблемы тестирования в ООП
Протоколирование состояний объектов и их
изменений:
Некоторые методы класса предназначены
не для выдачи информации пользователю,
а для изменения внутренних данных
объекта класса
2-65
Определение модуля
Проблемы тестирования в ООП
Значение внутренних данных объекта
определяет его состояние в каждый
определенный момент времени, а вызов
методов, изменяющих данные, изменяет и
состояние объекта
При тестировании классов необходимо
проверять, что класс адекватно реагирует
на внешние вызовы в любом из состояний
2-66
22
23. Учебный Центр Luxoft www.luxoft.ru/edu
Определение модуля
Проблемы тестирования в ООП
Однако, зачастую из-за инкапсуляции
данных невозможно определить
внутреннее состояние класса
программными способами внутри драйвера
Автоматизированное тестирование в этом
случае может лишь определить, по всем
ли выявленным состояниям
осуществлялись переходы и все ли
возможные реакции проверялись
2-67
Определение модуля
Проблемы тестирования в ООП
Тестирование изменений:
В результате рефакторинга только одного
класса, как правило, не меняется его
внешний интерфейс с другими классами
(интерфейсы меняются при рефакторинге
сразу нескольких классов)
2-68
Определение модуля
Проблемы тестирования в ООП
В результате обычных эволюционных
изменений системы у класса может
меняться внешний интерфейс:
по формальным признакам –изменяются
имена и состав методов, их параметры
по функциональным признакам – при
сохранении внешнего интерфейса меняется
логика работы методов (contract)
2-69
23
24. Учебный Центр Luxoft www.luxoft.ru/edu
Определение модуля
Проблемы тестирования в ООП
Для проведения модульного тестирования
класса после таких изменений потребуется
изменение драйвера и, возможно,
заглушек
Но только модульного тестирования в
данном случае недостаточно, необходимо
также проводить и интеграционное
тестирование данного класса вместе со
всеми классами, которые связаны с ним по
данным или по управлению 2-70
Определение модуля
Проблемы тестирования в ООП
Связь по управлению реализуется путем
вызова одного модуля из другого.
Вызванный модуль после завершения
своей работы возвращает управление
вызвавшему его модулю.
Связь по данным реализуется двумя
способами:
использование параметров при вызове
модулей
использование общих областей данных 2-71
Отличия модульного
тестирования и отладки
Определение отладки
Отладка — этап разработки
компьютерной программы, на котором
обнаруживают, локализуют и устраняют
ошибки
Чтобы понять, где возникла ошибка,
приходится:
узнавать текущие значения переменных
выяснять, по какому пути выполнялась
программа 2-72
24
25. Учебный Центр Luxoft www.luxoft.ru/edu
Отличия модульного
тестирования и отладки
Технологии отладки
Существуют две взаимодополняющие
технологии отладки:
Использование отладчиков — программ,
которые включают в себя
пользовательский интерфейс для
пошагового выполнения программы, с
остановками на указанных строках
исходного кода или при выполнении
определённого условия
2-73
Отличия модульного
тестирования и отладки
Технологии отладки
Вывод текущего состояния программы с
помощью расположенных в критических
точках программы операторов вывода —
на экран, принтер, или в файл (вывод
отладочных сведений в файл называется
журналированием)
2-74
Отличия модульного
тестирования и отладки
Проблемы при отладке
Однако использование отладки сопряжено с
рядом проблем:
Отладка метода, глубоко «закопанного» в
большом приложении, или
воспроизведение тестовой ситуации
зачастую становятся чрезвычайно
трудоемкими
2-75
25
26. Учебный Центр Luxoft www.luxoft.ru/edu
Отличия модульного
тестирования и отладки
Проблемы при отладке
Иногда не удается проверить только что
написанный код, потому что он еще нигде
и никак не используется
В некоторых ситуациях программисты
даже разрабатывают специальные
утилиты, позволяющие отладить тот или
иной компонент отдельно от всей системы
2-76
Отличия модульного
тестирования и отладки
Преимущества модульных тестов
При использовании модульных тестов
подобных проблем просто не возникает:
Если нужно что-нибудь проверить –
пишется соответствующий тест
Тесты представляют собой практически
идеальную отладочную среду: они
находятся полностью под контролем
программиста и позволяют вызвать любой
код в широком диапазоне условий 2-77
Отличия модульного
тестирования и отладки
Преимущества модульных тестов
Для большинства ошибок, найденных при
модульном тестировании, отладка вообще
не требуется, поскольку точно известны:
место их возникновения (код, который был
написан только что)
условия воспроизведения (тест, который
сейчас отлаживается)
2-78
26
27. Учебный Центр Luxoft www.luxoft.ru/edu
Организация модульного
тестирования
Фазы тестирования
Формально, процесс тестирования можно
разделить на следующие фазы:
планирование
разработка набора тестов
выполнение тестов и сбор статистики,
каждая из которых характеризуется
определенным набором активностей
2-79
Организация модульного
тестирования
Фаза планирования
На этапе планирования формируются общие
принципы тестирования в проекте:
степень полноты и охвата тестирования
источники входных и выходных данных
технологии проверки результатов и формат
их записи
требования к завершению тестирования
2-80
Организация модульного
тестирования
Фаза планирования
А так же анализируются свойства каждого из
модулей:
функциональные требования
дополнительные требования (напр.
системные)
характеристики входных и выходных
данных
определение состояний модуля (если
модуль можно представить в виде
конечного автомата) 2-81
27
28. Учебный Центр Luxoft www.luxoft.ru/edu
Организация модульного
тестирования
Фаза планирования
После анализа требований к модулям,
возможно возникнет необходимость внести
корректировки в общие принципы
тестирования
После этого фазу планирования можно
считать оконченной
2-82
Организация модульного
тестирования
Фаза разработки тестов
В ходе этапа разработки тестов должны
быть решены следующие задачи:
разработка архитектуры тестовых наборов
разработка тестовых сценариев (test-
case) и тестовых наборов (test-suite)
разработка нефункциональных тестов,
(напр., основанных на архитектуре)
составление спецификаций тестов
(документирование) 2-83
Организация модульного
тестирования
Фаза разработки тестов
тестовый сценарий – определение
набора входных данных теста, условий
выполнения и ожидаемых результатов,
указанных с целью оценки некоторого
аспекта тестируемого элемента
тестовый набор – набор тестовых
сценариев, объединенных по какому-либо
признаку (напр., тестирующих конкретный
модуль или его часть его
функциональности)
2-84
28
29. Учебный Центр Luxoft www.luxoft.ru/edu
Организация модульного
тестирования
Фаза разработки тестов
В ходе разработки тестовых сценариев так
же выполняются следующие задачи:
формируются тестовые наборы данных
создается тестовое окружение
осуществляется интеграция тестового
окружения с тестируемым модулем
2-85
Организация модульного
тестирования
Фаза выполнения и анализа
После того, как все тесты реализованы,
они выполняются в ручном или
автоматическом режиме
Вне зависимости от вида тестирования в
ходе этого этапа решаются две задачи:
выполнение тестовых примеров
сбор и анализ результатов тестирования
2-86
Организация модульного
тестирования
Фаза выполнения и анализа
Сбору подлежит следующая информация:
результат выполнения каждого тестового
сценария (прошел/не прошел)
информация об информационном
окружении системы в случае, если тест не
прошел
информация о ресурсах, которые
потребовались для выполнения тестового
примера
2-87
29
30. Учебный Центр Luxoft www.luxoft.ru/edu
Организация модульного
тестирования
Фаза выполнения и анализа
По результатам анализа этой информации
производится изменение требований,
программного кода, тестов или тестового
окружения
Этапы разработки (доработки), реализации
и выполнения тестов продолжаются до тех
пор, пока не будет достигнут критерий
завершения модульного тестирования
(напр., 90% покрытие тестами исходного
кода)
2-88
Использование mock- и
mock-
stub-объектов
stub-
Общие понятия
Классы (модули), как правило, редко
бывают полностью изолированными, и
используют в своей работе другие классы
Например, слой бизнес логики (Business
Logic Layer) часто работает с другими
объектами бизнес логики или обращается
к слою доступа к данным (Data Access
Layer)
2-89
Использование mock- и
mock-
stub-объектов
stub-
Общие понятия
В таких случаях на помощь приходят
mock-объекты (заглушки),
предназначенные для симуляции
поведения реальных объектов во время
тестирования
Понятие mock-объект может обозначать
как любой из видов заглушек (Test
Doublers, тестовых дублеров), так и
конкретный их вид – mock-объекты
2-90
30
31. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub-
Общие понятия
Все тест-дублеры делятся на 4 группы*:
dummy-объекты
fake-объекты
stub-объекты
mock-объекты
*Gerard Meszaros – “XUnit Test Patterns”, Martin Fawler – “Refactoring: Improving
the Design of Existing Code”
2-91
Использование mock- и
mock-
stub-объектов
stub-
Dummy-объекты
Dummy – пустые объекты, которые
передаются в вызываемые внутренние
методы, но не используются
(предназначены лишь для заполнения
параметров методов)
2-92
Использование mock- и
mock-
stub-объектов
stub-
Dummy-объекты
public void testInvoice_addLineItem() {
final int QUANTITY = 1;
Product product = new Product(getUniqueNumberAsString(),
getUniqueNumber());
City city = new City(“Vladivostok", “Russia”);
Address address = new Address(“Lenin St, 12", city, “650243");
Customer customer= new Customer(getUniqueNumberAsString(),
getUniqueNumberAsString(), address);
Invoice inv = new Invoice(customer);
// Вызов
inv.addItemQuantity(product, QUANTITY);
// Проверка
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
LineItem expItem = new LineItem(product, QUANTITY);
assertLineItemsEqual("",expItem, actual);
}
2-93
31
32. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub-
Dummy-объекты
public void testInvoice_addLineItem() {
final int QUANTITY = 1;
Product product = new Product(“Dummy product name”,
getUniqueNumber());
Invoice inv = new Invoice(new DummyCustomer);
// Вызов
inv.addItemQuantity(product, QUANTITY);
// Проверка
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
LineItem expItem = new LineItem(product, QUANTITY);
assertLineItemsEqual("",expItem, actual);
}
2-94
Использование mock- и
mock-
stub-объектов
stub-
Dummy-объекты
public class DummyCustomer implements ICustomer {
public DummyCustomer() {
// Конструктор оставляем пустым – никакой инициализации
не требуется
}
public int getTimeZone() {
throw new RuntimeException(“Этот метод не должен быть
вызван!”);
}
}
2-95
Использование mock- и
mock-
stub-объектов
stub -
Stub-объекты
Stub:
объекты, которые предоставляют заранее
заготовленные ответы на вызовы во время
выполнения теста и обычно не отвечающие ни
на какие другие вызовы, которые не
требуются в тесте
также могут запоминать какую-то
дополнительную информацию о количестве
вызовов, параметрах и возвращать их потом
тесту для проверки
2-96
32
33. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub -
Stub-объекты
Выделяют несколько видов stub’ов, в
зависимости от целей применения:
Responder (ответчик)
используется для эмуляции корректного
поведения объекта
как правило, используется в happy-path-
тестах
используется, когда реальный объект еще
не реализован, либо недоступен в
девелоперском окружении 2-97
Использование mock- и
mock-
stub-объектов
stub -
Stub-объекты
Saboteur (диверсант)
используется для эмуляции некорректного
поведения объекта
призван всеми возможными способами
вызвать «крах» системы, выдавая
некорректные значения, исключения и т.п.
вне зависимости от получаемых входных
данных
используется для тестирования обработки
различных отказов
2-98
Использование mock- и
mock-
stub-объектов
stub -
Stub-объекты
Temporary stub (временная заглушка)
используется для замены еще не
реализованного объекта
как правило, возвращает hardcoded-
значения
заменяется реальным объектом, как только
это становится возможным, либо сам
постепенно становится этим объектам,
постепенно получая функциональное
наполнение
2-99
33
34. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub -
Stub-объекты
Entity chain snipping
используется для замены сложной системы
взаимодействующих объектов одним
упрощает процедуру инициализации
тестового окружения
делает тесты более понятными
2-100
Использование mock- и
mock-
stub-объектов
stub -
Stub-объекты
В зависимости от реализации, stub’ы
бывают:
Hard-coded stub (статические)
на любые запросы выдают одно и то же
жестко прописанное значение
как правило, пишутся для конкретного
теста, либо их небольшого набора
2-101
Использование mock- и
mock-
stub-объектов
stub -
Stub-объекты
Configurable stub (конфигурируемые)
используются для того, чтобы для каждого
теста не писать свой статический stub
тест конфигурирует stub во время своей
инициализации
2-102
34
35. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub -
Fake-объекты
К сожалению, редко можно обойтись
простыми dummy- и stub-объектами
Иногда, тестируемый метод может
обращаться к базе данных, web-сервисам,
или файловой системе
В этом случае, наш объект должен уметь
«симулировать» требуемые действия,
выполняя более простой код (напр.,
сохранять данные в памяти вместо БД) 2-103
Использование mock- и
mock-
stub-объектов
stub -
Fake-объекты
Fake – объекты, имеющие работающие
реализации, но в таком виде, который
делает их неподходящими для production-
кода
Примеры fake-объектов:
Fake database – реальная БД заменяется
аналогичным по функциональности, но
более «легким» аналогом (который даст
выигрыш при тестировании, но не
выдержит production нагрузки)
2-104
Использование mock- и
mock-
stub-объектов
stub -
Fake-объекты
In-memory database – реальная БД
заменяется набором HashTable’s, либо её
небольшим «слепком», размещаемым в
памяти на время выполнения
Fake web-service – реальный web-сервис
заменяется локальной реализацией,
возвращающей определенное значение
(или набор значений), что позволяет
выполнять тесты вне зависимости от
доступности сервиса 2-105
35
36. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub -
Mock-объекты
Mock:
объекты, которые заменяют реальный
объект в условиях теста и позволяют
проверять вызовы своих членов как часть
системы или модульного теста
содержат заранее запрограммированные
ожидания вызовов, которые они должны
получить
применяются в основном для interaction
testing
2-106
Использование mock- и
mock-
stub-объектов
stub -
Mock-объекты
Во время инициализации теста, мы
создаем и настраиваем mock-объект
(определяем возвращаемые значения,
ожидаемые вызовы и их аргументы)
Во время выполнения, mock-объект
сравнивает получаемые вызовы и
значения с ожидаемыми, и «заваливает»
тест при несовпадении
По окончании теста проверяется наличие
методов, которые не были вызваны 2-107
Использование mock- и
mock-
stub-объектов
stub -
Mock-объекты
Рассмотрим пример: при удалении
пользователя, сообщение об этом должно
появляться в логе
public void TestRemoveUser() {
CommonUser expectedCU = createCommonUser();
UserManagementFacade facade =
new UserManagementFacadeImpl();
facade.removeUser(expectedCU.getUserNumber());
assert.False(“User should not exist after removing”,
facade.userExists(expectedCU.getUserNumber()));
}
2-108
36
37. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub -
Mock-объекты
public void TestRemoveUser_Mock() {
CommonUser expectedCU = createCommonUser();
MockAuditLog mockLog = new MockauditLog();
mockLog.setExpectedLogMessage(helper.getDate(),
helper.TEST_USER_NAME,
helper.USER_REMOVE_ACTION_CODE,
expectedCU.getUserNumber);
mockLog.setExpectedCallsNumber(1);
UserManagementFacade facade = new
UserManagementFacadeImpl();
facade.setAuditLog(mockLog);
facade.removeUser(expectedCU.getUserNumber());
assert.False(“User should not exist after removing”,
facade.userExists(expectedCU.getUserNumber()));
mockLog.verify();
} 2-109
Использование mock- и
mock-
stub-объектов
stub -
Mock-объекты
Реализация метода LogMessage
mock-объекта
public void LogMessage(Data actualDate, String actualUser,
String actualActionCode,
int actualUserNumber) {
actualCallsNumber++;
Assert.assertEquals(“date”, expectedDate, actualDate);
Assert.assertEquals(“user”, expectedUser, actualUser);
Assert.assertEquals(“action code”, expectedActionCode,
actualActionCode);
Assert.assertEquals(“number”, expectedNumber,
actualNumber);
} 2-110
Использование mock- и
mock-
stub-объектов
stub -
Подходы к модульному тестированию
State-based testing – подход, при
котором проверяется состояние объекта
после прохождение unit-теста
Interaction testing – подход к
модульному тестированию, при котором
тестируется взаимодействие объектов,
поведение методов, последовательность
их вызовов и т.п.
2-111
37
38. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub -
Подходы к модульному тестированию
В state-based testing нас интересует, в
какое состояние перешел объект после
вызова тестируемого метода, или что
вернул наш метод и правилен ли этот
результат
Подобные проверки проводятся при
помощи вызова методов класса Assert
различных unit-тест фреймворков:
Assert.AreEqual(),
Assert.IsNull() и т.д.
2-112
Использование mock- и
mock-
stub-объектов
stub -
Подходы к модульному тестированию
В interaction testing нас интересует прежде
всего не статическое состояние объекта, а
те динамические вызовы методов, которые
происходят у него внутри
В этом случае используют специальные
mock-фреймворки, содержащие
определенные конструкции для записи
ожиданий и их последующей проверки
(методы Verify(), VerifyAll() и т.п.)
2-113
Использование mock- и
mock-
stub-объектов
stub -
Подходы к модульному тестированию
Martin Fawler называет эти два подхода
классическим (classical) и мокистским
(mockist) unit-тестированием и делит
программистов на предпочитающих
первый и второй подходы
На самом деле, иногда просто удобнее
проверить состояние объекта, а иногда –
его взаимодействие с другими объектами
2-114
38
39. Учебный Центр Luxoft www.luxoft.ru/edu
Использование mock- и
mock-
stub-объектов
stub -
Подходы к модульному тестированию
Эти два подхода прекрасно уживаются
вместе, когда вы понимаете, о чем идет
речь, и что именно вы хотите сейчас
проверить
Точно так же, как уживаются в одном
тесте mock’и и stub’ы
2-115
План курса
Модуль 1: Модульные тесты
Тестирование как способ обеспечения
качества продукта
Уровни тестирования
Цели и задачи модульного тестирования
Покрытие кода
Унаследованный код
Организационные аспекты тестирования
2-116
Понятие покрытия
программного кода
Понятие полноты системы тестов
Одной из оценок качества системы тестов
является полнота – величина той части
функциональности системы, которая
проверяется тестами
Полная система позволяет утверждать,
что система реализует всю
функциональность, указанную в
требованиях
2-117
39
40. Учебный Центр Luxoft www.luxoft.ru/edu
Понятие покрытия
программного кода
Понятие полноты системы тестов
Кроме того, это позволяет утверждать, что
система не реализует никакой другой
функциональности
Степень покрытия программного кода
тестами – важный количественный
показатель, позволяющий оценить
качество как системы тестов, так и
тестируемой системы
2-118
Понятие покрытия
программного кода
Понятие полноты системы тестов
Одним из наиболее часто используемых
методов определения полноты системы
тестов является определение отношения
количества тест-требований, для которых
существуют тесты, к общему количеству
тест-требований
В данном случае речь идет о покрытии
тестами тест-требований
2-119
Понятие покрытия
программного кода
Понятие полноты системы тестов
В качестве единицы измерения степени
покрытия здесь выступает процент тест-
требований, для которых существуют
тесты
Покрытие требований позволяет оценить
степень полноты системы тестов по
отношению к функциональности системы,
но не позволяет оценить полноту по
отношению к ее программной реализации
2-120
40
41. Учебный Центр Luxoft www.luxoft.ru/edu
Понятие покрытия
программного кода
Понятие покрытия кода
Одна и та же функция может быть
реализована при помощи совершенно
различных алгоритмов, требующих
разного подхода к организации
тестирования
Для более детальной оценки полноты
системы тестов анализируется покрытие
программного кода, называемое также
структурным покрытием
2-121
Понятие покрытия
программного кода
Понятие покрытия кода
Во время работы каждого тестового
примера выполняется некоторый участок
программного кода системы
При выполнении всей системы тестов
выполняются все участки программного
кода, которые задействует эта система
тестов
2-122
Уровни покрытия
Уровни покрытия кода
Существует несколько различных способов
измерения покрытия, основные из них:
покрытие операторов
покрытие условий
покрытие путей
покрытие функций
покрытие вход/выход
2-123
41
42. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни покрытия
Покрытие операторов
Для обеспечения полного покрытия
программного кода на уровне операторов
необходимо, чтобы в результате
выполнения тестов каждый оператор был
выполнен хотя бы один раз
Перед началом тестирования необходимо
выделить переменные, от которых зависит
выполнение различных ветвей условий и
циклов в коде – управляющие входные
переменные 2-124
Уровни покрытия
Покрытие операторов
if (i == 0 || i == 101) {
if (showMessage) {
MessageBox.Show(“Входной параметр имеет
недопустимое значение ” + i.ToString());
} else {
System.Out.Writeln(“Входной параметр имеет
недопустимое значение ” + i.ToString());
}
return -1;
}
2-125
Уровни покрытия
Покрытие операторов
Для полного покрытия по операторам,
достаточно двух тестов:
i = 0, showMessage = true
i = 0, showMessage = false
Легко заметить, что при этом, тесты не
покрывают всей функциональности (не
протестировано поведение системы при
i = 101)
2-126
42
43. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни покрытия
Покрытие операторов
Также проблемы этого метода покрытия
можно увидеть и на примерах других
управляющих структур
Например, при проверке циклов do …
while – при данном уровне покрытия
достаточно выполнение цикла только один
раз, при этом метод совершенно
нечувствителен к логическим операторам
|| и &&
2-127
Уровни покрытия
Покрытие операторов
Другой особенностью данного метода
является зависимость уровня покрытия от
структуры программного кода
Рассмотрим простейший пример:
if (condition)
MethodA();
else
MethodB();
2-128
Уровни покрытия
Покрытие операторов
Если MethodA() содержит 99 операторов,
а MethodB() — один оператор, то
единственного теста, устанавливающего
condition в true, будет достаточно для
достижения 99%-го уровня покрытия
При этом аналогичный тестовый пример,
устанавливающий значение condition в
false, даст слишком низкий уровень
покрытия (1%)
2-129
43
44. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни покрытия
Покрытие условий
Для обеспечения полного покрытия
условий необходимо:
каждая точка входа и выхода в программе
и во всех ее функциях должна быть
выполнена по крайней мере один раз
все логические выражения в программе
должны принять каждое из возможных
значений хотя бы один раз
Таким образом, для покрытия по веткам
требуется как минимум два теста
2-130
Уровни покрытия
Покрытие условий
if (i == 0 || i == 101) {
if (showMessage) {
MessageBox.Show(“Входной параметр имеет
недопустимое значение ” + i.ToString());
} else {
System.Out.Writeln(“Входной параметр имеет
недопустимое значение ” + i.ToString());
}
return -1;
}
2-131
Уровни покрытия
Покрытие условий
Для покрытия предыдущего примера кода
по ветвям потребуется уже три теста
Это связано с тем, что первый условный
оператор if имеет неявную ветвь –
пустую ветвь else
Для обеспечения покрытия по ветвям
необходимо покрывать и пустые ветви
2-132
44
45. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни покрытия
Покрытие условий
Особенность данного уровня покрытия
заключается в том, что на нем могут не
учитываться логические выражения,
значения которых получаются вызовом
методов
Рассмотрим пример кода:
if (condition1 && (condition2 || Method()))
statement1;
else
statement2;
2-133
Уровни покрытия
Покрытие условий
Полное покрытие условий может быть
достигнуто при помощи двух тестов:
condition1 = true, condition2 = true
condition1 = false, condition2 = true/false
В обоих случаях не происходит вызова
метода Method() (хотя покрытие будет
полным)
Для его проверки необходимо добавить
еще один тест:
condition1 = true, condition2 = false
2-134
Уровни покрытия
Покрытие путей
В данном случае считаются все пути,
которые выполняются в процессе работы
тестируемого метода
Путь - уникальная последовательность
выполнения операторов, с учетом
условных операторов
Метод, содержащий в себе N условий,
имеет 2^N путей
Метод, содержащий цикл, может иметь
бесконечное число путей
2-135
45
46. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни покрытия
Покрытие путей
Т.о. в большинстве случаев 100%-е
покрытие путей обеспечить невозможно
Для решения этой проблемы, может быть
применен метод покрытия основных
(базисных, линейно-независимых)
путей
Основные пути – минимальный набор
путей, комбинация которых может
обеспечить все возможные пути
выполнения метода
2-136
Уровни покрытия
Покрытие путей
Число таких путей равно числу уникальных
условных операторов, увеличенное на 1
Рассмотрим следующий пример:
if (condition1)
statement1;
if (condition2)
statement2;
if (condition3)
statement3;
2-137
Уровни покрытия
Покрытие путей
Для достижения 100% покрытия основных
путей, нам потребуется 4 линейно-
независимых пути
Первый путь выбирается случайно (пусть
это будет путь, когда все условные
выражения принимают значение true)
Оставшиеся пути получаются поочередным
инвертированием одного из условных
выражений первого пути
2-138
46
47. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни покрытия
Покрытие путей
Таким образом, получаем четыре основных
пути, которые необходимо покрыть:
condition1 condition2 condition3
Path 1 true true true
Path 2 false true true
Path 3 true false true
Path 4 true true false
2-139
Уровни покрытия
Покрытие путей
В случае наличия циклов, может
использоваться следующий подход:
выделяем классы путей (к одному классу
можно отнести пути, отличающиеся
количеством итераций в конкретном цикле)
класс считается покрытым, если покрыт
хотя бы один путь из него
100% покрытие достигнуто, если покрыты
все классы путей
2-140
Уровни покрытия
Покрытие функций
Покрытие функций – каждая ли
функция тестируемого модуля является
выполненной хотя бы один раз
Является одним из самых простых методов
расчета покрытия, и дает довольно общее
представление о качестве тестируемого
модуля
С одной стороны, данное покрытие
говорит нам о том, что тестами покрыт
весь реализованный функционал модуля
2-141
47
48. Учебный Центр Luxoft www.luxoft.ru/edu
Уровни покрытия
Покрытие функций
С другой стороны, оно не гарантирует нам
адекватное поведение модуля, поскольку:
не проверяется реакция функций на все
возможные входные параметры
не проверяется реакция системы на все
возможные возвращаемые функцией
значения
2-142
Уровни покрытия
Покрытие вход/выход
Покрытие вход/выход – все ли
возможные варианты вызова функций и
возврата из них были выполнены
На данном уровне обеспечивается
тестирование как самих функций (все
возможные варианты вызова), так и их
взаимодействие в составе модуля (все
возможные варианты возврата)
2-143
Анализ покрытия
Цели и задачи анализа
К анализу покрытия программного кода
можно приступать только после полного
покрытия требований
Полное покрытие программного кода не
гарантирует того, что тесты проверяют все
требования к системе
Целью анализа полноты покрытия кода
является выявление участков кода,
которые не выполняются при выполнении
тестов 2-144
48
49. Учебный Центр Luxoft www.luxoft.ru/edu
Анализ покрытия
Цели и задачи анализа
В идеальном случае при полном покрытии
функциональных требований должно
получаться 100% покрытие кода
Однако на практике такое происходит
только в случае очень простого кода
Причины «недопокрытия» кода могут быть
различными
2-145
Анализ покрытия
Причины плохого покрытия кода
Недостатки в формировании тестов,
основанных на требованиях
тестовый набор должен быть дополнен
недостающими тестами
Неадекватности в требованиях
требования должны быть
модифицированы, после чего разработаны
и выполнены дополнительные тесты,
покрывающие новые требования
2-146
Анализ покрытия
Причины плохого покрытия кода
«Мертвый код»
этот код должен быть удален, и проведен
анализ для оценки эффекта удаления и
необходимости перепроверки
Дезактивируемый код – код,
работающий только в определенных
конфигурациях окружения
2-147
49
50. Учебный Центр Luxoft www.luxoft.ru/edu
Анализ покрытия
Причины плохого покрытия кода
Дезактивируемый код
для такого кода должна быть установлена
нормальная эксплуатационная среда, в
которой он выполняется
написаны тесты, покрывающие его
написаны тесты, проверяющие, что данный
код не может быть преднамеренно
выполнен в других конфигурациях
2-148
Анализ покрытия
Причины плохого покрытия кода
Избыточные условия
пример такого условия – выражение
!b || (a && b)
при b = false, значение переменной a не
имеет значения, т.е. условие избыточно и
вторая его часть не будет проверяться
Защитный код
2-149
Анализ покрытия
Причины плохого покрытия кода
Защитное программирование - это
метод организации программного кода
таким образом, чтобы при работе системы
последствия проявления дефектов в ней
не приводили к сбоям, отказам и авариям
(проверка входных данных, обработка
исключений и т.д.)
2-150
50
51. Учебный Центр Luxoft www.luxoft.ru/edu
Анализ покрытия
Причины плохого покрытия кода
Например, это может быть ветка default
в операторе выбора switch
Входное условие оператора switch может
принимать определенные значения
Как следствие, ветка default, возможно
никогда не будет выполнена
2-151
Анализ покрытия
Причины плохого покрытия кода
Защитное программирование, как правило,
не дает нам никакой информации о том,
где в системе находится дефект
Его нельзя рассматривать как замену
тестирования - эти два аспекта разработки
систем лишь дополняют друг друга
2-152
Анализ покрытия
Причины плохого покрытия кода
Также существуют случаи, когда
модульное тестирование кода сильно
затруднено, либо вообще невозможно:
генерация случайных чисел
сложные математические алгоритмы
параллельные алгоритмы
2-153
51