Java项目中使用groovy简化测试 、 java项目测试框架spock的使用教程
简介
Spock 框架是一个基于groovy语法的测试框架,由于使用groovy,所以使用起来比 junit 更加灵活,测试用例的写法更加简单易懂,一目了然。
如果使用过junit,spock的则很容易上手,可以类比来学习。
使用
下面直接使用实例来介绍spock的用法:
1.加入依赖
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.2-groovy-2.4</version>
<scope>test</scope>
</dependency>
<!-- Spock需要的groovy依赖 -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.15</version>
</dependency>
<!-- spring boot spock -->
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.2-groovy-2.4</version>
<scope>test</scope>
</dependency>
2. 测试方法的生命周期
在junit使用时,主要用以下注解来标记测试类的方法:
@Test :标记需要运行的测试方法,一个测试类中可以有多个@Test方法;
@Before/@After :标记的方法,会在每个测试方法运行之前/之后运行一次;
@BeforeClass/@AfterClass :标记的方法会在测试类初始化时/销毁时运行;
spock 没有使用以上的注解形式,而是测试类需要继承 Specification 父类,重写父类中的以下方法,就可以自定义测试方法的生命周期:
def setup() {} // run before every feature method
def cleanup() {} // run after every feature method
def setupSpec() {} // run before the first feature method
def cleanupSpec() {} // run after the last feature method
所以有如下测试代码:
package com.yawn.spock
import spock.lang.Shared
import spock.lang.Specification
/**
* spock 测试
* @author yawn
* 2019/6/10 9:43
*/
class CalculateSpec extends Specification {
// 初始化
def setupSpec() {
calculateService = new CalculateService()
println ">>>>>> setupSpec"
}
def setup() {
println ">>>>>> setup"
}
def cleanup() {
println ">>>>>> cleanup"
}
def cleanupSpec() {
println ">>>>>> cleanupSpec"
}
def "test life cycle"() {
given:
def a = 1
def b = 2
expect:
a < b
println "test method finished!"
}
}
运行结果为:
spock测试的生命周期方法执行顺序
3. 测试方法的格式
(1)given … expect … 格式:
given语句块为条件,expect为测试期望得到的结果,结果为true则通过测试。上面的示例就是这种格式的。
(2)given … when … then …
class CalculateSpec extends Specification {
@Shared
CalculateService calculateService
// 初始化
def setupSpec() {
calculateService = new CalculateService()
}
// 测试方法
def "test plus 1"() {
given: "准备数据"
def a = 1
def b = 2
when: "测试方法"
def c = calculateService.plus(a, b)
then: "校验结果"
c == 4 - 1
}
其中,@Share注解表示的是各个测试方法共享的一个实例。setupSpec() 方法中初始化了这个实例。
(3)when … then …
语义同上。
(4)given … expect … where …
def "test1"() {
given: "准备数据"
expect: "测试方法"
z == calculateService.plus(x, y)
where: "校验结果"
x | y || z
1 | 0 || 1
2 | 1 || 3
}
expect 为核心的测试校验语句块。where 为多个测试用例的列举,很直观的写法。
以上测试方法的语义为:z是由x和y经过方法plus()运算后得到的结果,现在分别列出了两组x,y,z的值,来测试这个关系是否满足。
由于有两个测试用例,所以plus()方法会在这里运行两次。
(5)expect … where …
同上。
(6)expect …
同上。测试单个语句是否成立。
4.where 测试用例的列举格式:
where 后可列举多个测试用例,有以下不同的格式:
// 1 映射格式
def "length of Spock's and his friends' names"() {
expect:
name.size() == length
where:
name | length
"Spock" | 5
"Kirk" | 4
"Scotty" | 6
}
// 2 数组列表格式 (每个数组顺序不能乱)
def "length of Yawn's and his friends' names"() {
expect:
name.size() == length
where:
name << ["Yawn", "Tim"]
length << [4, 3]
}
5.verifyAll 校验多个表达式结果
def "没有参数的 verifyAll"() {
when:
int z1 = calculateService.plus(1, 1)
int z2 = calculateService.plus(1, 2)
int z3 = calculateService.plus(1, 3)
then:
verifyAll {
z1 == 1
z2 == 3
z3 == 3
}
}
verifyAll语句块可以分别校验多个boolean的结果。
6.with()和verifyAll() 取对象属性的值
def "test person use with(p)"() {
given: "init a person"
Date now = new Date()
Person p = new Person(name: "yawn", age: 18, birthday: now)
expect: "测试p"
with(p) {
name == "yawn"
age < 20
birthday == now
}
}
def "多个预期值的测试使用 verifyAll()"() {
when:
Person p = new Person(name: "yawn", age: 18)
then:
verifyAll(p) {
name == "yawn"
age < 20
}
}
static class Person {
private String name
private int age
private Date birthday
}
with()和verifyAll()传入对象后,可以直接使用其属性值。
7.多次执行被测试的语句:
def "多次执行测试语句"() {
given:
def a = 0
expect: "aaa"
3 * calculateService.plusPlus(a) == 3
// 执行3次后结果为 3
}
“3 * _” 表示这个语句会被执行三次,再与“==”后面的3进行比较。
本文来自 java技术分享站(jvm123.com)http://jvm123.com/2019/08/spock.html