Статьи

Введение в Спока

Spock — это среда тестирования с открытым исходным кодом для Java и Groovy, которая привлекает все больше поклонников, особенно в сообществе Groovy. Это позволяет вам писать краткие, выразительные тесты, используя вполне читаемую нотацию в стиле BDD. Он даже поставляется с собственной встроенной библиотекой.

Ой. Я думал, что он был научно-фантастическим персонажем. Могу ли я увидеть пример?

Конечно. Вот простой код из ката кодирования, который я недавно сделал:

import spock.lang.Specification;

class RomanCalculatorSpec extends Specification {
def "I plus I should equal II"() {
given:
def calculator = new RomanCalculator()
when:
def result = calculator.add("I", "I")
then:
result == "II"
}
}

В Споке у вас нет тестов, у вас есть спецификации . Это обычные классы Groovy, которые расширяют класс спецификаций, который на самом деле является классом JUnit. Ваш класс содержит набор спецификаций, представленных методами с забавными названиями методов в кавычках ™. Забавный метод names-in-quotes ™ использует преимущества волшебства Groovy, чтобы вы могли выразить свои требования в очень удобочитаемой форме. А поскольку эти классы являются производными от JUnit, вы можете запускать их из Eclipse, как обычный модульный тест Groovy, и они создают стандартные отчеты JUnit, что хорошо для серверов CI.

Другое дело: обратите внимание на структуру этого теста? Мы используем Дано: , когда: а потом: выразить действия и ожидаемые результаты. Эта структура является обычной в поведенчески-ориентированной разработке, или BDD, таких фреймворках, как Cucumber и easyb. Хотя тесты в стиле Спока, как правило, более лаконичны и более технически ориентированы, чем такие инструменты, как Cucumber и easyb, которые часто используются для автоматизации приемочных испытаний. Но я отвлекся …

На самом деле, пример, который я привел ранее, был немного кратким. Мы могли бы сделать наши намерения более понятными, добавив текстовые описания после меток when: и then:, как я сделал здесь:

def "I plus I should equal II"() {
when: "I add two roman numbers together"
def result = calculator.add("I", "I")

then: "the result should be the roman number equivalent of their sum"
result == "II"
}

Это отличная прояснение ваших идей и документирование вашего API.

Но где же операторы AssertEquals?

Ага! Я рад, что ты спросил! Спок использует функцию под названием Power Asserts . Утверждение после того, как : ваше утверждение. Если этот тест не пройден, Спок покажет подробный анализ того, что пошло не так, в следующем формате:

I plus I should equal II(com.wakaleo.training.spocktutorial.RomanCalculatorSpec) 
Time elapsed: 0.33 sec <<< FAILURE!
Condition not satisfied:

result == "II"
| |
I false
1 difference (50% similarity)
I(-)
I(I)

at com.wakaleo.training.spocktutorial
.RomanCalculatorSpec.I plus I should equal II(RomanCalculatorSpec.groovy:17)

Ницца! Но в JUnit у меня есть @Before и @After для светильников. Могу ли я сделать это в Споке?

Конечно, но вы не используете аннотации. Вместо этого вы реализуете методы setup () и cleanup () (которые запускаются до и после каждой спецификации). Я добавил один здесь, чтобы показать вам, как они выглядят:

import spock.lang.Specification;

class RomanCalculatorSpec extends Specification {

def calculator
def setup() {
calculator = new RomanCalculator()
}

def "I plus I should equal II"() {
when:
def result = calculator.add("I", "I")
then:
result == "II"
}
}

Вы также можете определить setupSpec () и cleanupSpec (), которые запускаются непосредственно перед первым тестом и сразу после последнего.

Я большой поклонник параметризованных тестов в JUnit 4. Могу ли я сделать это в Споке!

Вы уверены, что можете! На самом деле это одна из черт Спока!

  def "The lowest number should go at the end"() {
when:
def result = calculator.add(a, b)

then:
result == sum

where:
a | b | sum
"X" | "I" | "XI"
"I" | "X" | "XI"
"XX" | "I" | "XXI"
"XX" | "II" | "XXII"
"II" | "XX" | "XXII"
}

Этот код будет запускать тест 5 раз. Переменные , Ь , а сумма инициализируются из строк в таблице в где: п. И если какой-либо из тестов не пройден, вы получите

Это тоже круто. Как насчет насмешек? Могу ли я использовать Mockito?

Конечно, если хочешь. но Спок на самом деле поставляется со своей собственной насмешливой структурой, которая довольно аккуратна. Вы устанавливаете макет или заглушку с помощью метода Mock (). Я показал два возможных способа использования этого метода здесь:

  given:
Subscriber subscriber1 = Mock()
def subscriber2 = Mock(Subscriber)
...

Вы можете настроить эти макеты на поведение определенным образом. Вот несколько примеров. Вы можете сказать, что метод должен возвращать определенное значение, используя оператор >> :

 subscriber1.isActive() >> true
subscriber2.isActive() >> false

Или вы можете получить метод, чтобы вызвать исключение при его вызове:

    subscriber.activate() >> { throw new BlacklistedSubscriberException() } 

Затем вы можете проверить результаты несколькими различными способами. Вот более сложный пример, чтобы показать вам некоторые из ваших вариантов:

def "Messages published by the publisher should only be received by active subscribers"() {

given: "a publisher"
def publisher = new Publisher()

and: "some active subscribers"
Subscriber activeSubscriber1 = Mock()
Subscriber activeSubscriber2 = Mock()

activeSubscriber1.isActive() >> true
activeSubscriber2.isActive() >> true

publisher.add activeSubscriber1
publisher.add activeSubscriber2

and: "a deactivated subscriber"
Subscriber deactivatedSubscriber = Mock()
deactivatedSubscriber.isActive() >> false
publisher.add deactivatedSubscriber

when: "a message is published"
publisher.publishMessage("Hi there")

then: "the active subscribers should get the message"
1 * activeSubscriber1.receive("Hi there")
1 * activeSubscriber2.receive({ it.contains "Hi" })

and: "the deactivated subscriber didn't receive anything"
0 * deactivatedSubscriber.receive(_)
}

Это выглядит аккуратно. Так что же лучше всего использовать Спока?

Спок отлично подходит для модульного или интеграционного тестирования проектов Groovy или Grails. С другой стороны, такие инструменты, как easyb amd cucumber , вероятно, лучше подходят для автоматизированных приемочных испытаний — формат менее технический, а отчетность больше подходит для тех, кто не является разработчиком.

From http://www.wakaleo.com/blog/303-an-introduction-to-spock