这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
书接上文,spock提出了很多概念去辅助我们快速mock数据,测试结果。如果这是诸如mockito之类的测试工具也能实现的,那下面的特性才是杀手锏——数据驱动测试。名字起的很好,可能还没到类似DDD那种高度,但首先已经被唬住了。
首先来看一个例子:
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
// exercise math method for a few different inputs
Math.max(1, 3) == 3
Math.max(7, 4) == 7
Math.max(0, 0) == 0
}
}
这是上文提到的一个普通的test case,但这并不是spock想要的效果。如果你的方法有10个分支,那就得在这写至少10行方法调用。代码多就是不正义,下面看一下spock是怎么精简的:
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b || c
1 | 3 || 3
7 | 4 || 7
0 | 0 || 0
}
}
这里可以写无限多的行,第一行是表头,下面是输入和期望的输出。具体的格式如下:
输入1 | 输入2 || 输出
当然也可以多写几个输入和输出,和第一行的参数值对应上即可。如果你不想用竖线,用分号也是可以的,毕竟敲起来可能稍微方便一些:
where:
a ; b ;; c
1 ; 3 ;; 3
7 ; 4 ;; 7
0 ; 0 ;; 0
对于写法上的花样,spock的开发者还提供了管道的写法,每个变量的值都是一个流水线:
where:
a << [1, 7, 0]
b << [3, 4, 0]
c << [3, 7, 0]
如果你依然还嫌麻烦,spock还提供了多变量的数据管道:
@Shared sql = Sql.newInstance("jdbc:h2:mem:", "org.h2.Driver")
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
[a, b, c] << sql.rows("select a, b, c from maxdata")
}
直接从数据库读取,然后直接给对应的变量赋值。如果你恰好又不想在sql中列举这么多字段,spock怎么可能不知道代码从业者的需求:
where:
[a, b, _, c] << sql.rows("select * from maxdata")
不想要的字段,在左侧直接用_忽略即可。如果还想玩出花来,spock也提供了多字段的组合:
where:
[a, [b, _, c]] << [
['a1', 'a2'].permutations(),
[
['b1', 'd1', 'c1'],
['b2', 'd2', 'c2']
]
].combinations()
这段组合的效果就是,a字段会变成['a1','a2']这样的List,中间的d会被忽略掉,b和c就分别对应b1,b2和c1,c2。这里还只是静态数据的罗列,变量计算也是可以支持的:
where:
a | b
3 | a + 1
7 | a + 2
0 | a + 3
在这样的框架体系下,能满足你绝大多数的想象力,应对不同的单测场景,单测似乎也不会那么枯燥了。