赞
踩
博主是一枚小新,经常挖坑填坑。最近在工作中遇到了这样一种情况。某天小伙伴说博主写得一个方法有问题,并且相应的测试类也跑不通。博主一直秉着磨刀不误砍柴工的思想,测试类都是写得好好地并且能杠杠运行的!怀着好奇,经过一番debug,发现某句代码抛出了空指针,如下
String url = linkedService.getUrlById(id);
getUrlById是通过id去查询数据库中的某条数据。问题到这里已经暴露无遗了,博主在测试该方法时将id写死,并且在数据库中能查出该条数据。而小伙伴的数据库中并没有这条数据,就导致了这个bug。最终,博主将sql语句发给小伙伴,测试通过了,问题似乎得到了**“解决”**,大家也皆大欢喜地继续做其他任务了。
然而,过了几天,博主在又遇到了相同的问题。
UserInfo user = userInfoService.getUser(id);
okok,这次博主一下子就定位到了问题的关键处,添加了相应的数据就解决了问题。但此时博主心里已经产生了一个疑问,并且在第二天例会时提了出来。
博主:“因为环境的改变(数据不同:每个同事维护自己的数据库,并没有使用共同的数据库),造成测试用例有时通过,有时不通过,这应该怎么有效的解决?”
孙大大:(博主的同事,喜欢专研问题并解决问题):“环境改变可能包括数据库,网络等其他因素,而你们遇到的这个问题,是测试用例写得不够自动化、专业化,在自己电脑上能测试并且通过,换到其他电脑上不能运行,这就是测试用例写得不够好。”
博主的好奇心一下子被吸引住了,如何解决这种问题,什么才能叫做写得好的测试用例?于是博主专门花了三天的时间阅读了 David Thomas 和Andrew Hunt 写的《单元测试之道Java版:使用JUnit》。这本书总共只有170多页,内容不多,没有啃大部头的那种挫败感,算是一本入门书籍,让我在短时间内了解如何使用JUnit编写单元测试。
一个单元测试是程序员写的一段代码,用于执行另一段代码并判断代码的行为是否与期望值一致。在实际中,为了验证行为和期望值是否一致,需要使用到assertion(断言)。它是一种非常简单的方法调用,用于判断某个语句是否为真。使用的时候需要在测试类中引入相应的方法
import static org.junit.Assert.*;
比如方法assertTrue将会检查给定的二元条件是否为真,如果条件非真,则该断言将会失败。具体的实现如下面所示:
public void assertTrue(boolean condition){
if(!condition){
abort();
}
}
我们可以利用该断言来检查两个数字是否相等:
assertTrue(a == 2);
如果由于某种原因,当调用assertTrue()的时候,a并不等于2,那么上面的程序将会中止并报错。
输出语句大家用的都不少,譬如现在要看一个pojo,在重写了它的toString()
方法后,利用如下方式输出
System.out.println(pojo);
logger.info("pojo={}",pojo);
接着就在满是日志的控制台里查找我们需要的信息。这种方法并不是不可取,但是效率低。如果你已经知道了期望值,那么最好使用断言来判断结果。
本小节内容引用自《单元测试之道Java版:使用JUnit》
我如何知道代码运行是否正确呢?
我要如何对它进行测试?
还有哪些方面可能会发生错误?
这个问题是否会在其他的地方出现呢?
测试任务可能失败的地方。
测试任何已经失败的地方。
对于新加的代码,在被证明正确之前,都可能是有问题的。
至少编写和产品代码一样多的测试代码。
针对每次编译都做局部测试。
签入代码之前做全局测试。
结果是否正确(Right)?
边界(boundary)条件是否正确?
是否可以检查反向(inverse)关联?
是否可以使用其他方法来跨检查(cross-check)结果?
错误条件(error condition)是否可以重新?
性能方面是否满足条件?
Automatic(自动的)。
Thorough(全面的)。
Repetable(可重复的)。
Independent(独立的)。
Professional(专业的)。
一致性(Conformance)——值是否符合预期的格式?
有序性(Ordering)——一组值是该有序的,还是无序的?
区间性(Range)——值是否在一个合理的最大值和最小值的范围之内?
引用、耦合性(Reference)——代码是否引用了一些不受代码本身直接控制的外部因素?
存在性(Existence)——值是否存在(例如,非null,非零,包含于某个集合等)
基数性(Cardinality)——是否恰好有足够的值?
时间性,绝对的或者相对的(Time)——所有事情是否都是按顺序发生的?是否在正确的时间?是否及时?
本章的主要目标是在Spring+SpringMVC+MyBatis的基础架构上,从传统的Dao、Service、Controller,由下往上针对这三层完成一次完整的测试。通过这个例子,希望大家能够更加了解测试如何编写。
本文采用JAVA 1.8.0_92
、Spring Framework 4.3.9.RELEASE
、 Junit 4.12
、mysql-5.6.32
通过测试,使用maven
构建项目、idea
作为编译器。
src/main/java/qingtian/example
程序的主要代码src/main/resources
config
配置文件mapper
mybatis映射文件sql
数据库脚本logback.xml
日志配置文件src/test
测试类Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。