文章目录
Spock测试套件
Spock套件基于一个单元测试框架,它有比junit更为简洁高效的测试语法。
核心概念
整体认识
Spock中一个单元测试类名叫Specification。所有的单元测试类,都需要继承Specification
class MyFirstSpecification extends Specification {
// fields
// fixture methods
// feature methods
// helper methods
}
对于spock来说,Specification代表了一个软件、应用、类的使用规范,其中的所有单元测试方法,被称为feature,即功能。
一个feature method的执行逻辑大概是如下几步:
- setup 设置该功能的前置配置
- stimulus 提供一个输入,触发该功能
- response 描述你期望该功能的返回值
- cleanup 清理功能的前置配置
所以,对spock来说,一个单元测试,其实是这个软件应用提供的功能使用规范,这个规范中提供了每个功能的使用说明书,输入什么,会得到什么,大体是按这个看法,去写单元测试的。
前置、后置
就像junit一样,我们可以对整个单元测试类做一些前置,并清理。也可以对每个单元测试的方法做一些前置后清理。
其跟Junit的类比关系为
setupSpec 对应 @BeforeClass
setup 对应 @Before
cleanup 对应 @After
cleanupSpec 对应 @AfterClass
同时由于Spock的单元测试本身是会集成Specification 父类的,所以父类中的前置、后置方法也会被调用,不过不用显示调用,会自动调用。
一个测试功能方法执行时,其整体的执行顺序为:
super.setupSpec
sub.setupSpec
super.setup
sub.setup
**feature method
sub.cleanup
super.cleanup
sub.cleanupSpec
super.cleanupSpec
同junit的类比
Feature 方法
blocks
feature的具体写法有很多的block组成,这些block对应的feature方法本身的四个阶段(setup, stimulus, reponse, cleanup) 。每个block对应阶段示意图
典型的用法
def '测试++'(){
given:
def x = 5
when: def result = calculateService.plusPlus(x)
then: result == 6
}
- given也可以写成setup,feature方法里的given其实跟外面的setup方法功能一样,都是做测试功能的前置设置。只是单独的setup方法,是用来写对每个测试feature都有用的测试。只跟当前feature相关的设置,请放在feature方法内的given标签
- when 标签用来实际调用想要测试的feature
- then 中对when的调用返回进行结果验证,这里不需要写断言,直接写表达式就是断言
异常condition
then中的断言在spock中叫condition。比如Java中的Stack在没有元素时,进行Popup,则会EmptyStackException异常。我们期望它确实会抛出这个异常,那么写法如下
def '异常2'() {
given:
def stack = new Stack()
when:
def result = stack.pop()
then:
EmptyStackException e = thrown()
}
它并不会抛出EmptyStackException,我们要测试这个预期的话,代码如下:
def '异常2'() {
given:
def stack = new Stack()
stack.push("hello world")
when:
stack.pop()
then:
EmptyStackException e = notThrown()
}
then和expect的区别
前面说了when block用来调用,then用来判断预期结果。但有的时候,我们的调用和预期判断并不复杂,那么可以用expect将两者合在一起,比如以下两段代码等价
when:
def x = Math.max(1, 2)
then:
x == 2
expect:
Math.max(1, 2) == 2
cleanup block的用法
def 'cleanup'() {
given:
def file = new File("/some/path")
file.createNewFile()
// ...
cleanup:
file.delete()
}
用于清理feature测试执行后的一些设置,比如打开的文件链接。该操作即便测试的feature出异常,依然会被调用
同样,如果多个测试feature都需要这个cleanup.那么建议将cleanup的资源提到setup方法中,并在cleanup方法中去清理
测试用例中的文本描述
为了让单元测试可读性更高,可以将测试方法中每一部分用文本进行描述,多个描述可以用and来串联
def '异常2'() {
given:'设置stack对象'
def stack = new Stack()
and:'其它变量设施'
stack.push('hello world')
when:'从sta