Tdd Workbook

3,269 views

Published on

Теоретический блок по модульному тестированию, junit и tdd patterns

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,269
On SlideShare
0
From Embeds
0
Number of Embeds
20
Actions
Shares
0
Downloads
56
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Tdd Workbook

  1. 1. Учебный Центр Luxoft www.luxoft.ru/edu Разработка через тестирование (Test Driven Development) Development) EKrivosheev@luxoft.com О вашем инструкторе Имя Статусы Контакты 1-2 Рабочие материалы Презентация Рабочая среда на ПК 1-3 1
  2. 2. Учебный Центр Luxoft www.luxoft.ru/edu Цели курса... курса... По окончании данного курса слушатели: получат общее понятие о целях и задачах тестирования освоят технологии модульного тестирования научатся применять шаблоны при разработке модульных тестов 1-4 Цели курса… курса… По окончании данного курса слушатели: ознакомятся с синтаксисом и приобретут опыт практического использования одной из сред тестирования семейства xUnit (JUnit/NUnit) освоят практику разработки через тестирование 1-5 ...Цели курса ...Цели По окончании данного курса слушатели: научаться применять шаблоны TDD получат практический опыт разработки приложения с использованием TDD 1-6 2
  3. 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. 4. Учебный Центр Luxoft www.luxoft.ru/edu Общие рекомендации Пожалуйста, Отключите телефоны Задавая вопросы, старайтесь придерживаться темы обсуждения Если у вас возникли вопросы, не относящиеся к теме, пометьте их, и инструктор будет рад ответить при подходящем случае 1-10 Организация обучения Время начала и конца занятий Перерывы Питание 1-11 Вопросы и ответы 1-12 4
  5. 5. Учебный Центр Luxoft www.luxoft.ru/edu План курса Модуль 1: Модульное тестирование Тестирование как способ обеспечения качества продукта Уровни тестирования Цели и задачи модульного тестирования Покрытие кода Унаследованный код Организационные аспекты тестирования 2-13 Тестирование – способ обеспечения качества продукта Качество ПО Качество программного продукта характеризуется набором свойств, определяющих, насколько продукт "хорош" с точки зрения заинтересованных сторон 2-14 Тестирование – способ обеспечения качества продукта Качество ПО Заинтересованными сторонами являются: заказчик продукта спонсор конечный пользователь разработчики тестировщики продукта инженеры поддержки сотрудники отделов маркетинга, обучения и продаж 2-15 5
  6. 6. Учебный Центр Luxoft www.luxoft.ru/edu Тестирование – способ обеспечения качества продукта Качество ПО Каждый из участников может иметь различное представление о продукте и о том, насколько он хорош или плох (то есть о том, насколько высоко качество продукта) 2-16 Тестирование – способ обеспечения качества продукта Качество ПО Таким образом, постановка задачи обеспечения качества продукта выливается в задачи: определения заинтересованных лиц их критериев качества нахождения оптимального решения, удовлетворяющего этим критериям 2-17 Тестирование – способ обеспечения качества продукта Тестирование: общие понятия Тестирование является одним из наиболее устоявшихся способов обеспечения качества разработки программного обеспечения Оно является одним из эффективных средств современной системы обеспечения качества программного продукта Верификация и валидация ПО 2-18 6
  7. 7. Учебный Центр Luxoft www.luxoft.ru/edu Тестирование – способ обеспечения качества продукта Тестирование: общие понятия С технической точки зрения, тестирование заключается в: выполнении приложения на некотором множестве исходных данных сверке получаемых результатов с заранее известными (эталонными) с целью установить соответствие различных свойств и характеристик приложения заказанным свойствам 2-19 Тестирование – способ обеспечения качества продукта Тестирование: общие понятия Тестирование является одной из основных фаз разработки программного продукта (наряду с Дизайном приложения и Разработкой кода) Оно характеризуется достаточно большим вкладом в суммарную трудоемкость разработки продукта 2-20 Тестирование – способ обеспечения качества продукта Эффективность автоматизации Широко известна оценка распределения трудоемкости между фазами создания программного продукта: 40%-20%-40%* (см. рисунок) Оценка распределения трудоемкости и стоимости исправления ошибки *Котляров В.П., Основы тестирования программного обеспечения 2-21 7
  8. 8. Учебный Центр Luxoft www.luxoft.ru/edu Тестирование – способ обеспечения качества продукта Эффективность автоматизации Следовательно, наибольший эффект в снижении трудоемкости может быть получен прежде всего на фазах Design и Testing А значит и основные вложения в автоматизацию или генерацию кода следует осуществлять, прежде всего, на этих фазах 2-22 Тестирование – способ обеспечения качества продукта Эффективность автоматизации Как видно из графика, стоимость исправления ошибок минимальна на стадиях дизайна и разработки Т.е. было бы неплохо обнаруживать большую часть ошибок до начала фазы тестирования 2-23 Тестирование – способ обеспечения качества продукта Эффективность автоматизации Однако технологии автоматизированного тестирования дизайна (верификации требований и спецификаций) только начинают появляться Трейсинг (дизайна и требований) В то же время, автоматизированное тестирование кода является широко распространенной практикой 2-24 8
  9. 9. Учебный Центр Luxoft www.luxoft.ru/edu Тестирование – способ обеспечения качества продукта Эффективность автоматизации Таким образом, процесс тестирования затрагивает все фазы производства ПО, однако не на всех фазах он может быть успешно автоматизирован 2-25 Тестирование – способ обеспечения качества продукта Уровни тестирования Разработка системы, как правило, идет на различных уровнях: вначале разрабатывается концепция системы, системные требования затем архитектура системы, ее разбиение на модули затем разрабатываются отдельные модули Процесс верификации также разбивается на отдельные уровни 2-26 План курса Модуль 1: Модульные тесты Тестирование как способ обеспечения качества продукта Уровни тестирования Цели и задачи модульного тестирования Покрытие кода Унаследованный код Организационные аспекты тестирования 2-27 9
  10. 10. Учебный Центр Luxoft www.luxoft.ru/edu Уровни тестирования Уровни тестирования системное тестирование, в ходе которого тестируется система в целом; интеграционное тестирование, в ходе которого тестируются группы взаимодействующих модулей и компонент системы; модульное тестирование, в ходе которого тестируются отдельные компоненты 2-28 Уровни тестирования Системное тестирование Системное тестирование (System Testing): Основной задачей системного тестирования является проверка как функциональных, так и нефункциональных требований в системе в целом 2-29 Уровни тестирования Системное тестирование В ходе системного тестирования выявляются следующие дефекты: неверное использование ресурсов системы непредусмотренные комбинации данных пользовательского уровня несовместимость с окружением непредусмотренные сценарии использования отсутствующая или неверная функциональность неудобство использования и т.д. 2-30 10
  11. 11. Учебный Центр Luxoft www.luxoft.ru/edu Уровни тестирования Системное тестирование Для минимизации рисков, связанных с особенностями поведения в системы в той или иной среде, во время тестирования рекомендуется использовать окружение максимально приближенное к тому, на которое будет установлен продукт после выдачи 2-31 Уровни тестирования Интеграционное тестирование Интеграционное тестирование (Integration Testing): Интеграционное тестирование предназначено для проверки связи между компонентами, а также взаимодействия с различными частями системы (операционной системой, оборудованием либо связи между различными системами) 2-32 Уровни тестирования Интеграционное тестирование Интеграционное тестирование так же может проводиться на различных уровнях: Компонентный: проверяется взаимодействие между компонентами системы после проведения компонентного (модульного) тестирования Системный: проверяется взаимодействие между разными системами после проведения системного тестирования 2-33 11
  12. 12. Учебный Центр Luxoft www.luxoft.ru/edu Уровни тестирования Модульное тестирование Компонентное или Модульное тестирование (Component or Unit Testing): Модульное тестирование проверяет функциональность и ищет дефекты в частях приложения, которые доступны и могут быть протестированы по отдельности (модули программ, объекты, классы, функции и т.д.) 2-34 Уровни тестирования Модульное тестирование Обычно компонентное (модульное) тестирование проводится вызывая код, который необходимо проверить (при поддержке среды разработки) Все найденные дефекты, как правило, исправляются в коде без формального их описания в системе управления ошибками 2-35 План курса Модуль 1: Модульные тесты Тестирование как способ обеспечения качества продукта Уровни тестирования Цели и задачи модульного тестирования Покрытие кода Унаследованный код Организационные аспекты тестирования 2-36 12
  13. 13. Учебный Центр Luxoft www.luxoft.ru/edu Цели и задачи модульного тестирования Модульное тестирование Каждая сложная программная система состоит из отдельных частей - модулей, выполняющих ту или иную функцию в составе системы Для того, чтобы удостовериться в корректной работе всей системы, необходимо вначале протестировать каждый модуль системы по отдельности 2-37 Цели и задачи модульного тестирования Модульное тестирование В случае возникновения проблем при тестировании системы в целом это позволяет проще выявить модули, вызвавшие проблему, и устранить соответствующие дефекты в них Такое тестирование модулей по отдельности получило называние модульного тестирования (unit testing) 2-38 Цели и задачи модульного тестирования Определения Тестовый драйвер (среда, фреймворк) – система, позволяющая выполнять и контролировать результат выполнения тестов. Как правило, позволяет также корректировать входные данные, включает в себя систему обработки исключительных ситуаций и восстановления, средства параметризации тестов и управления данными 2-39 13
  14. 14. Учебный Центр Luxoft www.luxoft.ru/edu Цели и задачи модульного тестирования Определения Заглушка – объект, предназначенный для симуляции поведения реального объекта во время тестирования Тест-план – представляет собой документ, в котором перечислены либо все тестовые примеры, необходимые для тестирования системы, либо часть тестовых примеров, объединенных по определенному признаку 2-40 Цели и задачи модульного тестирования Определения Тест-требования – содержат описание требований по проверке всех основных функций системы Для каждого модуля, подвергаемого тестированию, разрабатывается тестовое окружение, включающее в себя драйвер и заглушки, готовятся тест-требования и тест-планы, описывающие конкретные тестовые примеры 2-41 Цели и задачи модульного тестирования Цели модульного тестирования Основная цель модульного тестирования - удостовериться в соответствии требованиям каждого отдельного модуля системы перед тем, как будет произведена его интеграция в состав системы 2-42 14
  15. 15. Учебный Центр Luxoft www.luxoft.ru/edu Цели и задачи модульного тестирования Задачи модульного тестирования В ходе модульного тестирования решаются следующие основные задачи: Поиск и документирование несоответствий требованиям Поддержка разработки и рефакторинга низкоуровневой архитектуры системы и межмодульного взаимодействия Поддержка рефакторинга модулей Поддержка устранения дефектов и отладки2-43 Цели и задачи модульного тестирования Задачи модульного тестирования Рефакторинг – процесс полного или частичного преобразования внутренней структуры программы при сохранении её внешнего поведения. В его основе лежит последовательность небольших эквивалентных (т.е., сохраняющих поведение) преобразований. 2-44 Цели и задачи модульного тестирования Задачи модульного тестирования Поиск и документирование несоответствий требованиям - классическая задача тестирования, включающая в себя не только разработку тестового окружения и тестовых примеров, но и выполнение тестов, протоколирование результатов выполнения, составление отчетов о проблемах 2-45 15
  16. 16. Учебный Центр Luxoft www.luxoft.ru/edu Цели и задачи модульного тестирования Задачи модульного тестирования Поддержка разработки и рефакторинга низкоуровневой архитектуры системы и межмодульного взаимодействия – модульные тесты помогают выявить проблемы в дизайне системы и нелогичные или запутанные механизмы работы с модулем 2-46 Цели и задачи модульного тестирования Задачи модульного тестирования Поддержка устранения дефектов и отладки сопряжена с обратной связью, которую получают разработчики от тестировщиков в виде отчетов о проблемах 2-47 Цели и задачи модульного тестирования Задачи модульного тестирования Подробные отчеты о проблемах, составленные на этапе модульного тестирования, позволяют локализовать и устранить многие дефекты в программной системе на ранних стадиях ее разработки или разработки ее новой функциональности 2-48 16
  17. 17. Учебный Центр Luxoft www.luxoft.ru/edu Определение модуля Проблемы определения модуля В силу того, что модули, подвергаемые тестированию, обычно невелики по размеру, модульное тестирование считается наиболее простым (хотя и достаточно трудоемким) этапом тестирования системы Однако, несмотря на внешнюю простоту, с модульным тестированием сопряжены две проблемы: 2-49 Определение модуля Проблемы определения модуля не существует единых принципов определения того, что в точности является отдельным модулем трактовка понятия модульного тестирования - понимается ли под ним обособленное тестирование модуля, работа которого поддерживается только тестовым окружением, или речь идет о проверке корректности работы модуля в составе уже разработанной системы 2-50 Определение модуля Традиционное определение Традиционное определение модуля с точки зрения его тестирования: модуль - это компонент минимального размера, который может быть независимо протестирован в ходе верификации программной системы В реальности часто возникают проблемы с тем, что считать модулем 2-51 17
  18. 18. Учебный Центр Luxoft www.luxoft.ru/edu Определение модуля Альтернативные определения Существует несколько подходов к данному вопросу: модуль - это часть программного кода, выполняющая одну функцию с точки зрения функциональных требований модуль - это программный модуль, т.е. минимальный компилируемый элемент программной системы 2-52 Определение модуля Альтернативные определения модуль - это задача в списке задач проекта (с точки зрения его менеджера) модуль - это участок кода, который может уместиться на одном экране или одном листе бумаги модуль - это один класс или их множество с единым интерфейсом модуль - это одна функция или метод 2-53 Определение модуля Границы модуля Обычно за тестируемый модуль принимается либо программный модуль (единица компиляции) в случае, если система разрабатывается на процедурном языке, или класс, если система разрабатывается на объектно- ориентированном языке 2-54 18
  19. 19. Учебный Центр Luxoft www.luxoft.ru/edu Определение модуля Границы модуля В случае систем, написанных на процедурных языках, процесс тестирования модуля происходит достаточно просто – для каждого модуля разрабатывается: тестовый драйвер, вызывающий функции модуля и собирающий результаты их работы набор заглушек, которые имитируют поведение функций, содержащихся в других модулях 2-55 Определение модуля Границы модуля При тестировании объектно- ориентированных систем существует ряд особенностей, прежде всего вызванных инкапсуляцией данных и методов в классах (декомпозиция класса нарушит принцип инкапсуляции, согласно которому объекты каждого класса должны вести себя как единое целое с точки зрения других объектов) 2-56 Определение модуля Границы модуля Кроме того, более мелкое деление классов и использование отдельных методов в качестве тестируемых модулей нецелесообразно, поскольку для тестирования каждого метода потребуется разработка тестового окружения, сравнимого по сложности с уже написанным программным кодом класса 2-57 19
  20. 20. Учебный Центр Luxoft www.luxoft.ru/edu Определение модуля Компонентное тестирование Процесс тестирования классов как модулей иногда называют компонентным тестированием В ходе такого тестирования проверяется взаимодействие методов внутри класса и правильность доступа методов к внутренним данным класса 2-58 Определение модуля Компонентное тестирование На данном этапе возможно обнаружение не только стандартных дефектов (связанных с выходами за границы диапазона или неверно реализованными требованиями), но и специфических дефектов объектно-ориентированного программного обеспечения 2-59 Определение модуля Специфические дефекты ООП Такими дефектами являются: дефекты инкапсуляции, в результате которых, например, сокрытые данные класса оказываются недоступными для соответствующих публичных методов дефекты наследования, при наличии которых схема наследования блокирует важные данные или методы от классов- потомков 2-60 20
  21. 21. Учебный Центр Luxoft www.luxoft.ru/edu Определение модуля Специфические дефекты ООП дефекты полиморфизма, при которых полиморфное поведение класса оказывается распространенным не на все возможные классы дефекты инстанцирования, при которых во вновь создаваемых объектах класса не устанавливаются корректные значения по умолчанию параметров и внутренних данных класса 2-61 Определение модуля Проблемы тестирования в ООП Однако, выбор класса в качестве тестируемого модуля имеет и ряд сопряженных проблем: Определение степени полноты тестирования класса Протоколирование состояний объектов и их изменений Тестирование изменений 2-62 Определение модуля Проблемы тестирования в ООП Определение степени полноты тестирования класса: В том случае, если в качестве тестируемого модуля выбран класс, не совсем ясно, как определять степень полноты его тестирования Классический критерий полноты покрытия: тесты можно считать полными, если выполнены все структурные элементы всех методов, как публичных, так и скрытых 2-63 21
  22. 22. Учебный Центр Luxoft www.luxoft.ru/edu Определение модуля Проблемы тестирования в ООП Однако существует альтернативный подход к тестированию класса: все публичные методы должны предоставлять пользователю данного класса согласованную схему работы В этом случае достаточно проверить типичные корректные и некорректные сценарии работы с данным классом 2-64 Определение модуля Проблемы тестирования в ООП Протоколирование состояний объектов и их изменений: Некоторые методы класса предназначены не для выдачи информации пользователю, а для изменения внутренних данных объекта класса 2-65 Определение модуля Проблемы тестирования в ООП Значение внутренних данных объекта определяет его состояние в каждый определенный момент времени, а вызов методов, изменяющих данные, изменяет и состояние объекта При тестировании классов необходимо проверять, что класс адекватно реагирует на внешние вызовы в любом из состояний 2-66 22
  23. 23. Учебный Центр Luxoft www.luxoft.ru/edu Определение модуля Проблемы тестирования в ООП Однако, зачастую из-за инкапсуляции данных невозможно определить внутреннее состояние класса программными способами внутри драйвера Автоматизированное тестирование в этом случае может лишь определить, по всем ли выявленным состояниям осуществлялись переходы и все ли возможные реакции проверялись 2-67 Определение модуля Проблемы тестирования в ООП Тестирование изменений: В результате рефакторинга только одного класса, как правило, не меняется его внешний интерфейс с другими классами (интерфейсы меняются при рефакторинге сразу нескольких классов) 2-68 Определение модуля Проблемы тестирования в ООП В результате обычных эволюционных изменений системы у класса может меняться внешний интерфейс: по формальным признакам –изменяются имена и состав методов, их параметры по функциональным признакам – при сохранении внешнего интерфейса меняется логика работы методов (contract) 2-69 23
  24. 24. Учебный Центр Luxoft www.luxoft.ru/edu Определение модуля Проблемы тестирования в ООП Для проведения модульного тестирования класса после таких изменений потребуется изменение драйвера и, возможно, заглушек Но только модульного тестирования в данном случае недостаточно, необходимо также проводить и интеграционное тестирование данного класса вместе со всеми классами, которые связаны с ним по данным или по управлению 2-70 Определение модуля Проблемы тестирования в ООП Связь по управлению реализуется путем вызова одного модуля из другого. Вызванный модуль после завершения своей работы возвращает управление вызвавшему его модулю. Связь по данным реализуется двумя способами: использование параметров при вызове модулей использование общих областей данных 2-71 Отличия модульного тестирования и отладки Определение отладки Отладка — этап разработки компьютерной программы, на котором обнаруживают, локализуют и устраняют ошибки Чтобы понять, где возникла ошибка, приходится: узнавать текущие значения переменных выяснять, по какому пути выполнялась программа 2-72 24
  25. 25. Учебный Центр Luxoft www.luxoft.ru/edu Отличия модульного тестирования и отладки Технологии отладки Существуют две взаимодополняющие технологии отладки: Использование отладчиков — программ, которые включают в себя пользовательский интерфейс для пошагового выполнения программы, с остановками на указанных строках исходного кода или при выполнении определённого условия 2-73 Отличия модульного тестирования и отладки Технологии отладки Вывод текущего состояния программы с помощью расположенных в критических точках программы операторов вывода — на экран, принтер, или в файл (вывод отладочных сведений в файл называется журналированием) 2-74 Отличия модульного тестирования и отладки Проблемы при отладке Однако использование отладки сопряжено с рядом проблем: Отладка метода, глубоко «закопанного» в большом приложении, или воспроизведение тестовой ситуации зачастую становятся чрезвычайно трудоемкими 2-75 25
  26. 26. Учебный Центр Luxoft www.luxoft.ru/edu Отличия модульного тестирования и отладки Проблемы при отладке Иногда не удается проверить только что написанный код, потому что он еще нигде и никак не используется В некоторых ситуациях программисты даже разрабатывают специальные утилиты, позволяющие отладить тот или иной компонент отдельно от всей системы 2-76 Отличия модульного тестирования и отладки Преимущества модульных тестов При использовании модульных тестов подобных проблем просто не возникает: Если нужно что-нибудь проверить – пишется соответствующий тест Тесты представляют собой практически идеальную отладочную среду: они находятся полностью под контролем программиста и позволяют вызвать любой код в широком диапазоне условий 2-77 Отличия модульного тестирования и отладки Преимущества модульных тестов Для большинства ошибок, найденных при модульном тестировании, отладка вообще не требуется, поскольку точно известны: место их возникновения (код, который был написан только что) условия воспроизведения (тест, который сейчас отлаживается) 2-78 26
  27. 27. Учебный Центр Luxoft www.luxoft.ru/edu Организация модульного тестирования Фазы тестирования Формально, процесс тестирования можно разделить на следующие фазы: планирование разработка набора тестов выполнение тестов и сбор статистики, каждая из которых характеризуется определенным набором активностей 2-79 Организация модульного тестирования Фаза планирования На этапе планирования формируются общие принципы тестирования в проекте: степень полноты и охвата тестирования источники входных и выходных данных технологии проверки результатов и формат их записи требования к завершению тестирования 2-80 Организация модульного тестирования Фаза планирования А так же анализируются свойства каждого из модулей: функциональные требования дополнительные требования (напр. системные) характеристики входных и выходных данных определение состояний модуля (если модуль можно представить в виде конечного автомата) 2-81 27
  28. 28. Учебный Центр Luxoft www.luxoft.ru/edu Организация модульного тестирования Фаза планирования После анализа требований к модулям, возможно возникнет необходимость внести корректировки в общие принципы тестирования После этого фазу планирования можно считать оконченной 2-82 Организация модульного тестирования Фаза разработки тестов В ходе этапа разработки тестов должны быть решены следующие задачи: разработка архитектуры тестовых наборов разработка тестовых сценариев (test- case) и тестовых наборов (test-suite) разработка нефункциональных тестов, (напр., основанных на архитектуре) составление спецификаций тестов (документирование) 2-83 Организация модульного тестирования Фаза разработки тестов тестовый сценарий – определение набора входных данных теста, условий выполнения и ожидаемых результатов, указанных с целью оценки некоторого аспекта тестируемого элемента тестовый набор – набор тестовых сценариев, объединенных по какому-либо признаку (напр., тестирующих конкретный модуль или его часть его функциональности) 2-84 28
  29. 29. Учебный Центр Luxoft www.luxoft.ru/edu Организация модульного тестирования Фаза разработки тестов В ходе разработки тестовых сценариев так же выполняются следующие задачи: формируются тестовые наборы данных создается тестовое окружение осуществляется интеграция тестового окружения с тестируемым модулем 2-85 Организация модульного тестирования Фаза выполнения и анализа После того, как все тесты реализованы, они выполняются в ручном или автоматическом режиме Вне зависимости от вида тестирования в ходе этого этапа решаются две задачи: выполнение тестовых примеров сбор и анализ результатов тестирования 2-86 Организация модульного тестирования Фаза выполнения и анализа Сбору подлежит следующая информация: результат выполнения каждого тестового сценария (прошел/не прошел) информация об информационном окружении системы в случае, если тест не прошел информация о ресурсах, которые потребовались для выполнения тестового примера 2-87 29
  30. 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. 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. 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. 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. 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. 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. 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. 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. 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. 39. Учебный Центр Luxoft www.luxoft.ru/edu Использование mock- и mock- stub-объектов stub - Подходы к модульному тестированию Эти два подхода прекрасно уживаются вместе, когда вы понимаете, о чем идет речь, и что именно вы хотите сейчас проверить Точно так же, как уживаются в одном тесте mock’и и stub’ы 2-115 План курса Модуль 1: Модульные тесты Тестирование как способ обеспечения качества продукта Уровни тестирования Цели и задачи модульного тестирования Покрытие кода Унаследованный код Организационные аспекты тестирования 2-116 Понятие покрытия программного кода Понятие полноты системы тестов Одной из оценок качества системы тестов является полнота – величина той части функциональности системы, которая проверяется тестами Полная система позволяет утверждать, что система реализует всю функциональность, указанную в требованиях 2-117 39
  40. 40. Учебный Центр Luxoft www.luxoft.ru/edu Понятие покрытия программного кода Понятие полноты системы тестов Кроме того, это позволяет утверждать, что система не реализует никакой другой функциональности Степень покрытия программного кода тестами – важный количественный показатель, позволяющий оценить качество как системы тестов, так и тестируемой системы 2-118 Понятие покрытия программного кода Понятие полноты системы тестов Одним из наиболее часто используемых методов определения полноты системы тестов является определение отношения количества тест-требований, для которых существуют тесты, к общему количеству тест-требований В данном случае речь идет о покрытии тестами тест-требований 2-119 Понятие покрытия программного кода Понятие полноты системы тестов В качестве единицы измерения степени покрытия здесь выступает процент тест- требований, для которых существуют тесты Покрытие требований позволяет оценить степень полноты системы тестов по отношению к функциональности системы, но не позволяет оценить полноту по отношению к ее программной реализации 2-120 40
  41. 41. Учебный Центр Luxoft www.luxoft.ru/edu Понятие покрытия программного кода Понятие покрытия кода Одна и та же функция может быть реализована при помощи совершенно различных алгоритмов, требующих разного подхода к организации тестирования Для более детальной оценки полноты системы тестов анализируется покрытие программного кода, называемое также структурным покрытием 2-121 Понятие покрытия программного кода Понятие покрытия кода Во время работы каждого тестового примера выполняется некоторый участок программного кода системы При выполнении всей системы тестов выполняются все участки программного кода, которые задействует эта система тестов 2-122 Уровни покрытия Уровни покрытия кода Существует несколько различных способов измерения покрытия, основные из них: покрытие операторов покрытие условий покрытие путей покрытие функций покрытие вход/выход 2-123 41
  42. 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. 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. 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. 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. 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. 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. 48. Учебный Центр Luxoft www.luxoft.ru/edu Уровни покрытия Покрытие функций С другой стороны, оно не гарантирует нам адекватное поведение модуля, поскольку: не проверяется реакция функций на все возможные входные параметры не проверяется реакция системы на все возможные возвращаемые функцией значения 2-142 Уровни покрытия Покрытие вход/выход Покрытие вход/выход – все ли возможные варианты вызова функций и возврата из них были выполнены На данном уровне обеспечивается тестирование как самих функций (все возможные варианты вызова), так и их взаимодействие в составе модуля (все возможные варианты возврата) 2-143 Анализ покрытия Цели и задачи анализа К анализу покрытия программного кода можно приступать только после полного покрытия требований Полное покрытие программного кода не гарантирует того, что тесты проверяют все требования к системе Целью анализа полноты покрытия кода является выявление участков кода, которые не выполняются при выполнении тестов 2-144 48
  49. 49. Учебный Центр Luxoft www.luxoft.ru/edu Анализ покрытия Цели и задачи анализа В идеальном случае при полном покрытии функциональных требований должно получаться 100% покрытие кода Однако на практике такое происходит только в случае очень простого кода Причины «недопокрытия» кода могут быть различными 2-145 Анализ покрытия Причины плохого покрытия кода Недостатки в формировании тестов, основанных на требованиях тестовый набор должен быть дополнен недостающими тестами Неадекватности в требованиях требования должны быть модифицированы, после чего разработаны и выполнены дополнительные тесты, покрывающие новые требования 2-146 Анализ покрытия Причины плохого покрытия кода «Мертвый код» этот код должен быть удален, и проведен анализ для оценки эффекта удаления и необходимости перепроверки Дезактивируемый код – код, работающий только в определенных конфигурациях окружения 2-147 49
  50. 50. Учебный Центр Luxoft www.luxoft.ru/edu Анализ покрытия Причины плохого покрытия кода Дезактивируемый код для такого кода должна быть установлена нормальная эксплуатационная среда, в которой он выполняется написаны тесты, покрывающие его написаны тесты, проверяющие, что данный код не может быть преднамеренно выполнен в других конфигурациях 2-148 Анализ покрытия Причины плохого покрытия кода Избыточные условия пример такого условия – выражение !b || (a && b) при b = false, значение переменной a не имеет значения, т.е. условие избыточно и вторая его часть не будет проверяться Защитный код 2-149 Анализ покрытия Причины плохого покрытия кода Защитное программирование - это метод организации программного кода таким образом, чтобы при работе системы последствия проявления дефектов в ней не приводили к сбоям, отказам и авариям (проверка входных данных, обработка исключений и т.д.) 2-150 50
  51. 51. Учебный Центр Luxoft www.luxoft.ru/edu Анализ покрытия Причины плохого покрытия кода Например, это может быть ветка default в операторе выбора switch Входное условие оператора switch может принимать определенные значения Как следствие, ветка default, возможно никогда не будет выполнена 2-151 Анализ покрытия Причины плохого покрытия кода Защитное программирование, как правило, не дает нам никакой информации о том, где в системе находится дефект Его нельзя рассматривать как замену тестирования - эти два аспекта разработки систем лишь дополняют друг друга 2-152 Анализ покрытия Причины плохого покрытия кода Также существуют случаи, когда модульное тестирование кода сильно затруднено, либо вообще невозможно: генерация случайных чисел сложные математические алгоритмы параллельные алгоритмы 2-153 51

×