软件实施的过程
单元测试
集成测试
系统测试
验收测试
代码透明度
白盒测试
黑盒测试
灰盒测试
是否运行程序
所以,单元测试是一种动静态皆可的白盒测试
补充:测试实施者(内测、公测、验收)
α测试(内部人员测试,黑盒)
β测试(客户组织测试,验收阶段、黑盒)
第三方测试(请专门的安全机构检测软件的安全性)
- 测试目的:检验软件基本组成单位的正确性(方法、接口)
- 测试对象:软件的功能模块
- 测试方式:白盒测试
- 实施者:开发工程师/白盒测试工程师
单元测试实例分析
那么,在实际项目中,哪些模块(方法)需要写单元测试呢?每个被测试的模块需要写多少个测试用例呢?
强烈推荐dao层、srvice层的相对独立功能都一接口的方式声明,并在接口注释中写明模块的功能、也可以写一下实现需要注意的地方,不必写实现的细节。因此,每一个dao层、service层的接口声明的模块都需要测试,以及每一个controller接口。 有了接口,即使没有具体实现,在spock中可以直接使用接口实例化测试桩进行测试。
单元测试中,测试用例的设计通过等价类和边界值的方法设计,基本就可以满足需求。等价类就是将测试用例花费为若干个等价类,在每个等价类中至少取一个测试用例即可。边界值法是对等价类法的补充。
等价类划分必须满足简单路径覆盖。
例如:某个被测试模块的输入为整数,将测试用例可以划分为两个等价类(-∞, 0)和[0, +∞), 所以取了测试用例:-87,125。测试之后,我们总觉得不放心,所以我们取第三个测试用例 0再测一遍,这个0就是边界值法取的测试用例。
此外,对于多元测试用例,为了使用尽量少的测试用例,可以通过正交排列和正交表选取测试用例。
例如:某个被测试模块,输入为三个整数、每个输入都可以划分为两个等价类(-∞, 0)和[0, +∞),该如何选取测试用例?
- 简单工具类的测试
- 写一个main方法
- groovy脚本
- 使用单元测试框架 junit/spock(maven、gradle自动化执行,ant支持junit和junitreport任务)
- spring环境中的测试
- 使用单元测试框架 junit/spock
常用方法注解:
@Before @BeforeClass @After @AfterClass @Test @Ignore
测试方法上使用注解,并且测试方法必须是 类型的,返回值必须为。
0. groovy环境安装配置
groovy环境安装配置和入门使用示例
1. 依赖
<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>
2. 继承Specification类,四类个方法和测试方法
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!" } }
3. 测试方法的6中基本标签语句组合形式
- given … expect …
- given … when … then …
- when … then …
- given … expect … where …
- expect … where …
- expect
4. 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 } }
5. 多次执行被测试方法
def "多次执行测试语句"() { given: def a = 0 expect: "aaa" 3 * calculateService.plusPlus(a) == 3 // 执行3次后结果为 3 }
*6. spock对异常的测试
thrown()方法
测试的结果需要抛出某个异常时使用,实例如下:
/ * 测试一个方法抛出异常,可以使用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()方法
测试的结果不能抛出某个异常时使用,实例如下:
/ * notThrown() 表示被测试的方法不会抛出某种异常 */ def "HashMap accepts null key"() { given: def map = new HashMap() when: map.put(null, "elem") then: notThrown(NullPointerException) }
我们通过以上方法来测试HashMap是否允许null作为键,如果测试通过(不会抛出异常),则表示可以用null。
*7. HamcrestMatcher
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 = when: int b = a / 10 then: // HamcrestSupport.expect(b, HamcrestMatchers.closeTo(10000, 200)) // expect(b, closeTo(10000, 200)) expect b, closeTo(10000, 200) } }
1. 使用数据管道
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中使用小括号) }
2. 使用数据表(数据管道的语法糖)
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 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 } }
mock和stub测试桩的区别
- mock测试桩多用于检测结果。
- stub测试桩多用于提供测试的条件。
stub给模块提供一个或多个返回结果(方法的返回值)
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 }
mock给被测试的模块提供一个用于校验的动作
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 }
@Ignore
忽略测试方法
@IgnoreRest
忽略其他测试方法
@Unroll
展开:数据驱动测试中,展开所有的测试结果,分别显示每个测试用例的测试情况
@FailsWith(ArithmeticException.class)
- 记录已经知道的 bug
- 标记让方法执行失败的测试用例
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到此这篇单元测试项目(单元测试项目包括)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/te-unit/26701.html