Я влюбился. Официально. Со споком.
Хорошо, мы только болтались немного, здесь и там. Но одна из вещей, которые я делаю, — это подготовка к обновленному докладу о дополнениях 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 через две недели, а позже опубликую свою презентацию. Я надеюсь увидеть некоторых из вас там.