软件实施的过程
单元测试
集成测试
系统测试
验收测试
代码透明度
白盒测试
黑盒测试
灰盒测试
是否运行程序
静态测试:目测看代码
动态测试:debug
所以,单元测试是一种动静态皆可的白盒测试
补充:测试实施者(内测、公测、验收)
α测试(内部人员测试,黑盒)
β测试(客户组织测试,验收阶段、黑盒)
第三方测试(请专门的安全机构检测软件的安全性)
那么,在实际项目中,哪些模块(方法)需要写单元测试呢?每个被测试的模块需要写多少个测试用例呢?
强烈推荐dao层、srvice层的相对独立功能都一接口的方式声明,并在接口注释中写明模块的功能、也可以写一下实现需要注意的地方,不必写实现的细节。因此,每一个dao层、service层的接口声明的模块都需要测试,以及每一个controller接口。 有了接口,即使没有具体实现,在spock中可以直接使用接口实例化测试桩进行测试。
单元测试中,测试用例的设计通过等价类和边界值的方法设计,基本就可以满足需求。等价类就是将测试用例花费为若干个等价类,在每个等价类中至少取一个测试用例即可。边界值法是对等价类法的补充。
等价类划分必须满足简单路径覆盖。
例如:某个被测试模块的输入为整数,将测试用例可以划分为两个等价类(-∞, 0)和[0, +∞), 所以取了测试用例:-87,125。测试之后,我们总觉得不放心,所以我们取第三个测试用例 0再测一遍,这个0就是边界值法取的测试用例。
此外,对于多元测试用例,为了使用尽量少的测试用例,可以通过正交排列和正交表选取测试用例。
例如:某个被测试模块,输入为三个整数、每个输入都可以划分为两个等价类(-∞, 0)和[0, +∞),该如何选取测试用例?
常用方法注解:
@Before
@BeforeClass
@After
@AfterClass
@Test
@Ignore
测试方法上使用@Test
注解,并且测试方法必须是public
类型的,返回值必须为void
。
<dependencies>
<!-- Spock需要的groovy依赖 -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.15</version>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.2-groovy-2.4</version>
<scope>test</scope>
</dependency>
<!-- spring spock -->
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.2-groovy-2.4</version>
<scope>test</scope>
</dependency>
</dependencies>
import spock.lang.Specification
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!"
}
}
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 "多次执行测试语句"() {
given:
def a = 0
expect: "aaa"
3 * calculateService.plusPlus(a) == 3
// 执行3次后结果为 3
}
测试的结果需要抛出某个异常时使用,实例如下:
/**
* 测试一个方法抛出异常,可以使用try-catch在when语句块中捕获验证,但是写起来比较繁琐
* 所以,Spock测试框架中可以使用thrown()来表示这种现象,并且可以返回异常的实例
*/
def "test Thrown"() {
when:
int a = 1
int b = 0
int c = 2
c = (a / b)
then:
def ex = thrown(Exception)
ex instanceof ArithmeticException
// ArithmeticException 异常时我们预料之中的
}
测试的结果不能抛出某个异常时使用,实例如下:
/**
* notThrown() 表示被测试的方法不会抛出某种异常
*/
def "HashMap accepts null key"() {
given:
def map = new HashMap()
when:
map.put(null, "elem")
then:
notThrown(NullPointerException)
}
我们通过以上方法来测试HashMap是否允许null作为键,如果测试通过(不会抛出异常),则表示可以用null。
import static spock.util.matcher.HamcrestSupport.expect
import static spock.util.matcher.HamcrestMatchers.closeTo
class HamcrestSupportSpec extends Specification {
def "test for closeTo()"() {
given:
int a = 101256
when:
int b = a / 10
then:
// HamcrestSupport.expect(b, HamcrestMatchers.closeTo(10000, 200))
// expect(b, closeTo(10000, 200))
expect b, closeTo(10000, 200)
}
}
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a << [1, 7, 0]
b << [3, 4, 0]
c << [3, 7, 0]
}
@Shared sql = Sql.newInstance("jdbc:mysql://localhost:3306/test", "com.mysql.jdbc.Driver", "root", "root")
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where: "多变量的数据管道"
[a, b, c] << sql.rows("select a, b, c from maxdata")
// [[a, b, c], [a, c]] 这种写法类似于Matlab和Lisp语言中二维表、多维表的写法(Lisp中使用小括号)
}
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b || c
1 | 3 || 3
7 | 4 || 7
0 | 0 || 0
}
使用@SpringBootTest
@ContextConfiguration
启动spring容器,注入bean进行测试即可。
如下:
@SpringBootTest
@ContextConfiguration
class SpringBootSpec extends Specification {
@Shared
CalculateService calculateService
def "spring boot test"() {
expect: "asas"
z == calculateService.minus(x, y)
where:
x << [9, 8, 7]
y << [6, 5, 4]
z << [3, 3, 3]
}
def "spring boot test2"() {
expect: "asas"
z == calculateService.minus(x, y)
where:
x | y | z
9 | 8 | 1
6 | 5 | 1
3 | 3 | 0
}
}
def "Stub 测试桩"() {
given: "构造测试桩"
CalculateInterface calculateService = Stub(CalculateInterface)
calculateService.plusPlus(_) >> 1
when:
int x = calculateService.plusPlus(12)
int y = calculateService.plusPlus(3)
then:
x == 1
y == 1
}
def subscriber = Mock(Subscriber) // 1. 创建一个mock对象
def "should send messages subscriber"() {
when:
publisher.send("hello") // 2. publisher 发送一个“hello”
then:
1 * subscriber.receive("hello") // 3. subscriber 接收到一个“hello”
1 * subscriber.messageCount == 1
}
忽略测试方法
忽略其他测试方法
展开:数据驱动测试中,展开所有的测试结果,分别显示每个测试用例的测试情况
groovy.sql.Sql
访问数据库groovy-sql模块是比java中jdbc更高一级的对数据库操作的抽象,可以理解为groovy中的jdbc。
使用实例:
def url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC&characterEncoding=UTF-8&useUnicode=true"
def sql = Sql.newInstance(url, "root", "root", "com.mysql.cj.jdbc.Driver")
List<GroovyRowResult> testList = sql.rows("select * from test")
for (GroovyRowResult row : testList) {
println row
println row.get("id")
println row.get("name")
println row.get("remark")
}
println testList
sql.close()
参考 http://jvm123.com/2019/10/groovy-sql.html
本堂课演示代码下载地址
git clone https://gitee.com/yawensilence/demo-spock.git
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。