Spock — это новая среда тестирования и спецификации для разработчиков на Java и Groovy. Когда я распространял информацию о Споке, у меня часто возникал вопрос: «С какой стати мне нужен еще один фреймворк для тестирования? Разве уже не достаточно клонов xUnit / xSpec?» В этом посте я постараюсь показать вам, чем отличается Спок, и почему это стоит поближе.
Утверждения
Утверждения являются наиболее фундаментальным способом выражения поведения части программного обеспечения. Это почти традиция, что каждая новая среда тестирования поставляется с собственным API подтверждения, добавляя несколько складок тут и там, и называя вещи немного по-другому. Например, чтобы сказать, что две вещи равны, вы обычно пишете что-то вроде:
- assertEquals (x, y)
- x.shouldEqual (у)
- x.mustBe (у)
Время от времени появляется незнакомец и спрашивает, не может ли он просто использовать простые логические выражения вместо API утверждений. Но мы все знаем, что логические выражения не могут сказать нам, почему они потерпели неудачу. Или они могут? Знакомьтесь, Спок!
@Speck
class Assertions {
def "comparing x and y"() {
def x = 1
def y = 2
expect:
x < y // OK
x == y // BOOM!
}
}
В Споке утверждения следуют за ожидаемым: label, и это именно то, что просил незнакомец — простые логические выражения! Вот что мы получаем, когда запускаем этот тест:
Condition not satisfied:
x == y
| | |
1 | 2
false
Конечно, это работает не только для простых сравнений, но и для произвольных утверждений. Вот еще один, немного более интересный вывод:
Condition not satisfied:
Math.max(a, b) > c
| | | | |
112 | 94 | 115
112 false
Опять же, среда выполнения Спока собрала всю необходимую информацию и представила ее интуитивно понятным способом. Хорошо, не правда ли?
Управляемые данными тесты
Хотя управляемое данными тестирование является естественным продолжением тестирования на основе состояния, оно, похоже, используется не очень часто. Я полагаю, это потому, что тестовые среды делают написание тестов, управляемых данными, довольно сложными. Все они? Знакомьтесь, Спок!
@Speck
class DataDriven {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a << [7, 4, 9]
b << [3, 5, 9]
c << [7, 5, 9]
}
}
Блок ожидания предоставляет только тестовую логику, используя свободные (т.е. неопределенные) переменные a, b и c в качестве заполнителей для данных. Затем до блока where можно связать конкретные значения с этими переменными. Когда этот тест выполняется, он повторяется три раза: сначала с a = 7, b = 3 и c = 7; тогда с а = 4, б = 5 и с = 5; и наконец с a = b = c = 9.
Конечно, данные теста не должны быть включены в тест. Например, давайте попробуем загрузить его из базы данных:
@Speck
class DataDriven {
@Shared sql = Sql.newInstance("jdbc:derby:spockdata", "org.apache.derby.jdbc.EmbeddedDriver")
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
row << sql.rows("select * from maxdata")
a = row["a"]
b = row["b"]
c = row["c"]
}
Здесь значения a, b и c берутся из столбцов с одинаковыми именами в таблице maxdata, пока не останется больше строк. Используя синтаксис, похожий на множественное назначение Groovy, блок where может быть еще более упрощен:
where:
[a, b, c] << sql.rows("select a, b, c from maxdata")
Вместе с созданием экземпляра Sql, описанного выше, теперь у нас осталось две строки кода для загрузки наших тестовых данных из базы данных. Насколько это легко?
Резюме
Утверждения и тесты на основе данных — это только две области, в которых Спок достигает большего с меньшими затратами. На http://spockframework.org вы также познакомитесь с невероятно скудной насмешливой структурой Спока, его механизмом расширения на основе перехвата и другими захватывающими формами жизни. Если у вас есть какие-либо вопросы или предложения, напишите нам по адресу http://groups.google.com/group/spockframework или отправьте вопрос по адресу http://issues.spockframework.org . Я с нетерпением жду ваших отзывов!
Питер Нидервизер
Основатель Spock Framework
http://spockframework.org