Я влюбился. Официально. Со споком.
Хорошо, мы только болтались немного, здесь и там. Но одна из вещей, которые я делаю, — это подготовка к обновленному докладу о дополнениях Spring Roo в SpringOne / 2GX. Вместо того, чтобы повторять то же самое снова, я хотел показать некоторую практическую помощь людям, пишущим дополнения, например, как писать хорошие тесты.
Кроме того, я хотел бы отметить несколько вещей, которые требуют дополнительной работы, поднять некоторые проблемы для очереди JIRA , чтобы мы могли улучшить Roo после SpringOne. Мы вернемся к этому позже в этой статье.
Тестирование доступности дополнений
Проверка доступности команды установки надстройки для доступа к оболочке Roo может быть немного сложной. Например, в дополнении Spock Roo я ожидаю, что оболочка пользователя выглядит так:
- работает в контексте проекта
- проект должен содержать две зависимости maven для спок-ядра и спок-пружины
- проект должен содержать одну зависимость, чтобы плагин gmaven мог запускать тесты Спока
Итак, есть несколько сценариев для тестирования. Я начал тестировать их по отдельности. Плохой разработчик Во-первых, здесь есть своего рода таблица правды:
installedDependencies | installedPlugins | ожидаемый результат |
---|---|---|
никто | никто | правда |
Депа, Депб | никто | правда |
DEPA | плагин | правда |
baddep | никто | правда |
Депа, Депб | плагин | ложный |
депабадверсия, депб | плагин | правда |
Дано :
- depa и depb = правильные две зависимости Maven,
- baddep — это зависимость Maven, совершенно не связанная
- depabadversion — та же зависимость, но другая версия
- плагин это плагин gmaven от Codehaus
- Ожидаемый результат — можем ли мы пойти дальше и установить надстройку (т.е. заменить то, что есть)
Когда я начал третий метод, я увидел столько дублирования, что начал отступать. Сначала я удалил все дополнительные вызовы, которые я делал, к различным методам (таким как projectOperations.getDependencies ()), что облегчало тестирование (и отладку). Затем я вытащил синтаксис таблицы данных.
Вот чем я закончил. Абсолютно босс, кстати :
package org.sillyweasel.roo.addons.spock import org.springframework.roo.project.Dependency import org.springframework.roo.project.Plugin import org.springframework.roo.project.ProjectOperations import org.springframework.roo.project.maven.Pom import spock.lang.Unroll class SpockOperationsImplTest extends spock.lang.Specification { static def depa = new Dependency("org.springframework", "spock-core", "0.6-groovy-1.8") static def depb = new Dependency ("org.springframework", "spock-spring", "0.6-groovy-1.8") static def depabadversion = new Dependency("org.springframework", "spock-core", "0.6-groovy-1.0") static def baddep = new Dependency ("org.springframework", "sbad", "0.6-groovy-1.8") static def plugin = new Plugin("org.codehaus.gmaven", "gmaven-plugin", "1.4") @Unroll def "install check - #situation"() { given: def pom = Mock(Pom.class) def operations = new SpockOperationsImpl() def projectOperations = Mock(ProjectOperations.class) operations.projectOperations = projectOperations when: def commandAvailable = operations.isSetupCommandAvailable() then: 1 * projectOperations.isFocusedProjectAvailable() >> true 1 * projectOperations.getFocusedModule() >> pom 1 * pom.getDependencies() >> deps pom.getBuildPlugins() >> plugins assert commandAvailable == res where: deps | plugins | res | situation [] | [] | true | "no installedDependencies or installedPlugin" [ depa, depb] | [] | true | "all installedDependencies... but no installedPlugin" [ depa ] | [plugin]| true | "some installedDependencies... and installedPlugin" [ baddep ] | [] | true | "a different dependency and no plugins" [ depa, depb ]| [plugin]| false | "all installedDependencies and installedPlugin" [ depabadversion, depb ] | [plugin] | true | "bad version of a plugin" } }
Что еще лучше …
Видите название метода вверху? Он имеет встроенную хэш-метку и использует поле `ситуация` плюс аннотация` @ Unroll`, чтобы превратить метод в пять отдельных методов тестирования на лету во время тестирования. Niiiice!
Проблемы Ру — тестирование аддонов
Почему я выполняю все свои тесты в Groovy, когда Roo является платформой на основе Java? Три причины:
- Я хочу кататься на дополнениях,
- Мне нужно понять слабые стороны API дополнения, чтобы попытаться улучшить его,
- Мне нужно убедиться, что я тестирую большинство кода с наименьшими усилиями!
К средней точке: Roo основан на Maven и Spring. Он управляет файлом Maven `pom.xml`, а также Spring, Java и другими артефактами.
Поскольку файлы Maven управляются некоторыми классами-оболочками Java, написанными с целью генерации POM Maven , в настоящее время они достаточно хороши — вы можете заполнить их , например, с помощью Xml DOM , но они не являются тестируемыми по своей природе.
Например, класс Pom нельзя смоделировать, поэтому я не могу внедрить поддельный набор зависимостей или плагинов. То есть, если я не установлю две тестовые зависимости Maven, обе из которых Спок сказал мне использовать в качестве полезного совета! К ним относятся: `cglib-nodep` для имитации классов без интерфейса и` objenesis` для создания экземпляров классов как Mocks без конструкторов без аргументов. Для остроумия:
<dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>2.2.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.objenesis</groupId> <artifactId>objenesis</artifactId> <version>1.2</version> <scope>test</scope> </dependency>
С этим я могу использовать:
def pom = Mock(Pom.class)
До встречи на SpringOne / 2GX
Я расскажу об этом и других методах в SpringOne / 2GX через две недели, а позже опубликую свою презентацию. Я надеюсь увидеть некоторых из вас там.