Spock android что это

Моки, стабы и шпионы в Spock Framework

Spock предоставляет 3 мощных (но разных по сути) инструмента, упрощающих написание тестов: Mock, Stub и Spy.

Довольно часто коду, который нужно протестировать, требуется взаимодействовать с внешними модулями, называющимися зависимостями (в оригинальной статье используется термин collaborators, который не очень распространён в русскоязычной среде).

Модульные тесты чаще всего разрабатываются для тестирования одного изолированного класса при помощи различных вариантов моков: Mock, Stub и Spy. Так тесты будут надёжнее и будут реже ломаться по мере того, как код зависимостей эволюционирует.

Такие изолированные тесты менее подвержены проблемам при изменении внутренних деталей реализации зависимостей.

От переводчика: каждый раз, когда я использую Spock Framework для написания тестов, я чувствую, что могу ошибиться при выборе способа подмены зависимостей. В этой статье есть максимально краткая шпаргалка по выбору механизма для создания моков.

Mocks

Используйте Mock для:

  • проверки контракта между тестируемым кодом и зависимостями
  • проверки того, что методы зависимостей вызываются корректное число раз
  • проверки корректности параметров, с которыми вызывается код зависимостей

Stubs

Используйте Stub для:

  • предоставления предопределённых результатов вызовов
  • выполнения предопределённых действий, ожидаемых от зависимостей, таких как выбрасывание исключений

Spies

Бойтесь шпионов (Spy). Как сказано в документации Spock:

Подумайте дважды, прежде чем использовать этот механизм. Возможно, вам стоит изменить дизайн вашего решения и реорганизовать ваш код.

Но так уж случается, что бывают ситуации, когда мы должны работать с легаси кодом. Легаси код бывает сложно или даже невозможно протестировать при помощи моков и стабов. В этом случае есть всего один вариант решения — использовать Spy.

Лучше иметь легаси код, покрытый тестами с использованием Spy, чем не иметь тестов для легаси совсем.

Используйте Spy для:

  • тестирования легаси кода, который невозможно протестировать другими методами
  • проверки того, что методы зависимостей вызываются корректное число раз
  • проверки корректности передаваемых параметров
  • предоставления предопределённого ответа от зависимостей
  • выполнения предопределённых действий в ответ на вызовы методов зависимостей

Mocks

Вся сила моков проявляется, когда задача модульного теста состоит в проверке контракта между тестируемым кодом и зависимостями. Давайте посмотрим на следующий пример, где у нас имеется контроллер FooController , который использует FooService в качестве зависимости, и протестируем эту функциональность при помощи моков.

В этом сценарии мы хотим написать тест, который проверит:

  • контракт между FooController и FooService
  • FooService.doSomething(name) вызывается корректное число раз
  • FooService.doSomething(name) вызывается с корректным параметром

Взглянем на тест:

Приведённый тест создаёт мок сервиса:

Также тест проверяет, что FooService.doSomething(name) вызывается один раз, и параметр, переданный в него, совпадает со строкой «Sally» .

Приведённый код решает 4 важные задачи:

  • создаёт мок для FooService
  • убеждается в том, что FooService.doSomething(String name) вызывается ровно один раз с параметром String и значением «Sally»
  • изолирует тестируемый код, заменяя реализацию зависимости
Читайте также:  Карты джипиэс для андроид

Stubs

Использует ли тестируемый код зависимости? Является ли целью тестирования удостовериться, что тестируемый код работает корректно при взаимодействии с зависимостями? Являются ли результаты вызовов методов зависимостей входными значениями для тестируемого кода?

Если поведение тестируемого кода изменяется в зависимости от поведения зависимостей, то вам необходимо использовать стабы (Stub).

Давайте посмотрим на следующий пример с FooController и FooService и протестируем функциональность контроллера при помощи стабов.

Создать стаб можно так:

Приведённый код решает 4 важные задачи:

  • создаёт стаб FooService
  • убеждается в том, что FooService.doSomething(String name) вернёт строку «Stub did something» независимо от переданного параметра (поэтому мы использовали символ _ )
  • изолирует тестируемый код, заменяя реализацию зависимости на стаб

Spies

Пожалуйста не читайте этот раздел.

Пропускайте и переходите к следующему.

Всё ещё читаете? Ну что ж, хорошо, давайте разбираться со Spy.

Не используйте Spy. Как сказано в документации Spock:

Подумайте дважды, прежде чем использовать этот механизм. Возможно, вам стоит изменить дизайн вашего решения и реорганизовать ваш код.

При этом бывают ситуации, когда нам приходится работать с легаси кодом. Легаси код бывает невозможно протестировать с помощью моков или стабов. В этом случае шпион остаётся единственным жизнеспособным вариантом.

Шпионы отличаются от моков или стабов, потому что они работают не как заглушки.

Когда зависимость подменяется моком или стабом, создается тестовый объект, а настоящий исходный код зависимости не выполняется.

Шпион, с другой стороны, выполнит основной исходный код зависимости, для которой был создан шпион, но шпион позволит вам изменять то, что возвращает шпион, и проверять вызовы методов, так же как моки и стабы. (Отсюда и название Spy).

Давайте посмотрим на следующий пример FooController , который использует FooService , а затем протестируем функциональность с помощью шпиона.

Создать экземпляр-шпион довольно просто:

В приведённом коде шпион позволяет нам проверить вызов FooService.doSomething(name) , количество вызовов и значения параметров. Более того, шпион изменяет реализацию метода, чтобы вернуть другое значение.

Приведённый код решает 4 важные задачи:

  • создаёт экземпляр шпион для FooService
  • проверяет взаимодействие с зависимостями
  • проверяет, как приложение работает в соответствии с определёнными результатами вызовов методов зависимостей
  • изолирует тестируемый код, заменяя реализацию зависимости на стаб

Какой из вариантов использовать: Mock, Stub или Spy?

Это вопрос, с которым сталкиваются многие разработчики. Этот FAQ может помочь, если вы не уверены, какой из подходов использовать.

Q: Является ли целью тестирования проверка контракта между тестируемым кодом и зависимостями?

A: Если вы ответили Да, используйте Mock

Q: Является ли целью тестирования удостовериться, что тестируемый код работает верно при взаимодействии с зависимостями?

A: Если вы ответили Да, используйте Stub

Q: Являются ли результаты вызовов методов зависимостей входными значениями для тестируемого кода?

A: Если вы ответили Да, используйте Stub

Q: Работаете ли вы с легаси кодом, который очень сложно протестировать, и у вас не осталось вариантов?

Читайте также:  Источник телепрограммы для iptv андроид url

A: Попробуйте использовать Spy

Код примеров

Вы можете найти код всех примеров этой статьи по ссылке:

Источник

Зачем нам вулканец на борту: обзор Spock Framework

Автоматизация тестирования помогает постоянно контролировать качество IT-продукта, а также снижать затраты в долгосрочной перспективе. В автоматизации существуют различные подходы, например, Behavior Driven Development (BDD), разработка через поведение.

С этим подходом связаны инструменты cucumber, robot framework, behave и другие, в которых разделены сценарии выполнения и реализация каждой конструкции. Такое разделение помогает составить удобочитаемые сценарии, но требует значительных затрат времени и поэтому может быть непрактичным при написании реализации.

Рассмотрим, как можно упростить работу с BDD, используя подходящие инструменты – например, фреймворк Spock, который сочетает в себе красоту, удобство принципов BDD и особенности jUnit.

Spock framework

Spock – фреймворк для тестирования и спецификации приложений на языках Java и Groovy. Благодаря использованию в качестве основы платформы JUnit этот фреймворк совместим со всеми популярными IDE (в частности, IntelliJ IDEA), различными инструментами сборки (Ant, Gradle, Maven) и continuous integration (CI) серверами.

Как пишут разработчики фреймворка, Spock «вдохновлен JUnit, RSpec, jMock, Mockito, Groovy, Scala, вулканцами и другими увлекательными формами жизни».

В этой статье мы рассмотрим последнюю доступную версию, Spock Framework 2.0. Ее особенности: возможность использования JUnit5, Java 8+, groovy 2.5 (также существует сборка с версией 3.0). Spock распространяется по лицензии Apache 2.0 и имеет отзывчивое сообщество пользователей. Разработчики фреймворка продолжают дорабатывать и развивать Spock, который уже включает в себя множество расширений, позволяющих тщательно настроить запуск тестов. Например, одно из наиболее интересных анонсированных направлений доработки – это добавление параллельного исполнения тестов.

Groovy

Groovy является объектно-ориентированным языком программирования, разработанным для платформы Java как дополнение с возможностями Python, Ruby и Smalltalk. Groovy использует Java-подобный синтаксис с динамической компиляцией в JVM байт-код и напрямую работает с другим Java-кодом и библиотеками. Язык может использоваться в любом Java-проекте или как скриптовый язык.

К особенностям groovy относятся: как статическая, так и динамическая типизация; встроенный синтаксис для списков, массивов и регулярных выражений; перегрузка операций. При этом замыкания в Groovy появились задолго до Java.

Groovy хорошо подходит для быстрой разработки тестов, когда есть возможность применять «синтаксический сахар», схожий с python, и не задумываться о типизации объектов.

Особенности Spock Framework

Одна из ключевых особенностей фреймворка – у разработчика есть возможность писать спецификации с ожидаемыми характеристиками системы с использованием принципов BDD подхода. Этот подход позволяет составлять бизнес-ориентированные функциональные тесты для программных продуктов с высокой предметной и организационной сложностью.

Спецификация представляет собой класс groovy, расширяющий spock.lang.Specification

Спецификация может содержать различные вспомогательные поля, которые инициируются для каждого класса спецификации.

С помощью аннотации @Shared можно дать доступ к полю классам-наследникам спецификации.

Методы настройки класса спецификации:

В следующей таблице рассмотрим, у каких ключевых слов и методов Spock framework есть аналоги в JUnit.

Блоки теста

В Spock Framework каждая фаза теста выделена в отдельный блок кода (см. пример в документации).

Читайте также:  Сбп сбербанк настройка андроид

Блок кода начинается с лейбла и завершается началом следующего блока кода или окончанием теста.

Блок given отвечает за настройку начальных условий теста.

Блоки when, then всегда используются вместе. В блоке when – стимулятор, раздражитель системы, а в блоке then – ответная реакция системы.

В тех случаях, когда есть возможность сократить конструкцию when-then до одного выражения, можно использовать один блок expect. Далее будут использованы примеры из официальной документации Spock framework:

или одно выражение

Блок cleanup применяют для освобождения ресурсов перед следующей итерацией теста.

Блок where применяют для передачи данных для тестирования (Data Driven Testing).

Виды передачи входных данных будут рассмотрены далее.

Пример реализации теста на Spock Framework

Далее рассмотрим подходы к реализации тестирования веб-страницы авторизации пользователя в системе с использованием selenium.

Здесь мы видим базовый класс спецификации страницы. В начале класса мы видим импорт необходимых классов. Далее представлена аннотация shared, позволяющая классам-наследникам получить доступ к веб-драйверу. В блоке setup() мы видим код инициализации веб-драйвера и открытия веб-страницы. В блоке cleanup() – код завершения работы веб-драйвера.

Далее перейдем к обзору спецификации страницы авторизации пользователя.

Спецификация страницы авторизации наследуется от базовой спецификации страниц. Аннотация Issue задает идентификатор теста во внешней системе трекинга (например, Jira). В следующей строке мы видим название теста, которое по соглашению задается строковыми литералами, что позволяет использовать любые символы в названии теста (в том числе и русскоязычные). В блоке given происходит инициализация page object класса страницы авторизации, а также получение корректных логина и пароля для авторизации в системе. В блоке when выполняется действие по авторизации. В блоке then – проверка ожидаемого действия, а именно – успешная авторизация и переадресация на главную страницу системы.

На примере данной спецификации мы видим наиболее значимый плюс использования парадигмы BDD в spock – спецификация системы одновременно является и ее документацией. Каждый тест описывает определенное поведение, каждый шаг в тесте имеет свое описание, понятное не только разработчикам, но и заказчикам. Описание блоков может быть представлено не только в исходном коде теста, но и в диагностических сообщениях или отчетах о работе теста.

В фреймворке предусмотрена возможность передавать различные логины и пароли для тестирования (параметризировать тест).

Data Driven Testing в Spock Framework

Data Driven Testing = table-driven testing = parameterized testing

Для тестирования сценария с несколькими параметрами можно использовать различные варианты их передачи.

Таблицы данных (Data Tables)

Рассмотрим несколько примеров из официальной документации фреймворка.

Каждая строка в таблице – отдельная итерация теста. Также таблица может быть представлена и одним столбцом.

_ — объект-заглушка класса спецификации.

Для лучшего визуального восприятия параметров можно переписать пример выше в следующем виде:

Теперь мы видим, что a, b – входные параметры, а c – ожидаемое значение.

Потоки данных (Data pipes)

В некоторых случаях использование таблицы параметров будет выглядеть очень громоздко. В таких случаях можно применять следующий вид передачи параметров:

Источник

Оцените статью