企业级规范说明框架
Spock 是一个为 JVM 开发者设计的测试、规范说明及打桩(mocking)框架,它强调代码的可读性与清晰度。通过结合 BDD 概念和 Groovy 简洁的语法,Spock 帮助团队编写出易于理解且维护愉悦的测试用例。
编写易于阅读和理解的测试,即使是非程序员也能看懂。
通过内置支持创建灵活且强大的 Mock 和 Stub 对象。
与 JUnit 5+ 及各种构建工具无缝集成。
使用不同的数据集轻松运行相同的测试用例。
充分利用 Groovy 语言的强大功能与灵活性。
使用丰富的匹配器集合,清晰地验证预期结果。
// CalculatorSpec.groovy
import spock.lang.Specification
class CalculatorSpec extends Specification {
def "Test calculate method: #a #operation #b = #expectedResult"() {
given: "A calculator instance"
def calculator = new Calculator()
expect: "The calculation should match the expected value"
calculator.calculate(a, b, operation) == expectedResult
where: "Define test data"
a | b | operation || expectedResult
1 | 2 | "+" || 3
5 | 3 | "-" || 2
4 | 2 | "*" || 8
10 | 2 | "/" || 5
-1 | 1 | "+" || 0
1 | -1 | "-" || 2
-2 | -2 | "*" || 4
-4 | -2 | "/" || 2
1 | 1 | "+" || 42 // A failing test case
}
def "Test calculate method with division by zero"() {
given: "A calculator instance"
def calculator = new Calculator()
when: "Perform division by zero"
calculator.calculate(10, 0, "/")
then: "An IllegalArgumentException is thrown"
def exception = thrown(IllegalArgumentException)
and: "The exception message is correct"
exception.message == "Cannot divide by zero"
}
def "Test calculate method with invalid operation"() {
given: "A calculator instance"
def calculator = new Calculator()
when: "Perform calculation with invalid operation"
calculator.calculate(1, 2, "**")
then: "An IllegalArgumentException is thrown"
def exception = thrown(IllegalArgumentException)
and: "The exception message is correct"
exception.message == "Invalid operation: **"
}
}
// Calculator.groovy
class Calculator {
/**
* Performs arithmetic operations on two integers.
*
* @param a The first integer.
* @param b The second integer.
* @param operation The operation to perform (+, -, *, /).
* @return The result of the operation.
* @throws IllegalArgumentException if the operation is invalid or division by zero is attempted.
*/
int calculate(int a, int b, String operation) {
switch (operation) {
case "+": return a + b
case "-": return a - b
case "*": return a * b
case "/":
if (b == 0) {
throw new IllegalArgumentException("Cannot divide by zero")
}
return a / b
default:
throw new IllegalArgumentException("Invalid operation: " + operation)
}
}
String toString() {
return "Calc"
}
}
Spock 清晰的 given:、when:、then: 代码块让理解测试逻辑变得直观。
╷
└─ Spock ✔
└─ CalculatorSpec ✔
├─ Test calculate method: #a #operation #b = #expectedResult ✔
│ ├─ Test calculate method: 1 + 2 = 3 ✔
│ ├─ Test calculate method: 5 - 3 = 2 ✔
│ ├─ Test calculate method: 4 * 2 = 8 ✔
│ ├─ Test calculate method: 10 / 2 = 5 ✔
│ ├─ Test calculate method: -1 + 1 = 0 ✔
│ ├─ Test calculate method: 1 - -1 = 2 ✔
│ ├─ Test calculate method: -2 * -2 = 4 ✔
│ ├─ Test calculate method: -4 / -2 = 2 ✔
│ └─ Test calculate method: 1 + 1 = 42 ✘ Condition not satisfied:
│
│ calculator.calculate(a, b, operation) == expectedResult
│ | | | | | | |
│ Calc 2 1 1 + | 42
│ false
├─ Test calculate method with division by zero ✔
└─ Test calculate method with invalid operation ✔