Упрощаем тестирование и программирование с Groovy DSL

Сложный страшный код для создания тестовых данных

Тут я даже не стал показывать пример заполнения каких-либо списков, это просто превращается в муку. Но я же не поплакать этот пост пишу!

Ищем решение

Я думаю многие писали такое и не испытывали положительных эмоций. Есть конечно другой вариант — написать простой билдер в стиле Java:

Уже намного лучше! Мы даже смогли без боли в нижней части позвоночника сформировать список Repairs. Но появились специфичные проблемы:

  • Потеряли смысл аттрибутов, например что такое «487511577896511» в crashRepair совсем непонятно
  • Мы начали использовать громоздкие конструкции setAttributeValue
  • Для поддержки такого решения требуется множество статических функций: car(..), crashRepair(..), machineComponents(..), scheduledRepair(..)

Я думаю многим хотелось бы видеть тестовые данные вот в таком виде:

Вот это то, что мы искали! Прекрасный пример с минимальной избыточностью и прекрасной структурой!

DSL и Groovy

Groovy — прекрасный динамический язык, позволяющий творить чудеса (хотя это часто кажется безумием).

Начнём с основ, с замыканий (Closure). Это объекты, по сути являющиеся функциями, которые имеют контекст выполнения. В них возможно использовать внешние переменные и методы вызывающего кода. Для этого у замыкания есть свойство delegate. Фактически это объект, у которого запрашиваются недостающие функции и переменные. Вот таким нехитрым образом можно заставить замыкание использовать наш объект для вызовов:

И можно использовать например так:

Здесь в замыкании вызывается метод plateNumber у объекта car, в который передаётся строка ‘IDDQD’.

Не супер конечно, но уже есть идеи как сделать конфетку.

И теперь мы видим уже вполне симпатичный код:

Ну и полный пример для ленивых:

Думаю в работе это может пригодиться, ведь даже в Java проектах многие леняться использовать Builder для тестов. Хотя многие ленятся писать тесты, ну тут уж я им ничем не помогу.

P.S. ещё в качестве исходных данных можно использовать объекты в сериализованном виде: JSON или XML, в использовании не очень удобно, но иногда этого хватает. Только стоит помнить, что интроспекции IDE ничего не смогут проверить в ваших данных. А если вы ищете статически типизированное решение, то лучше паттерна Builder ничего нет.

Facebooktwittergoogle_plusredditlinkedin