你们可能对以下情景比较熟悉:javascript
如上问题,估计只要是个开发人员,均可能遇到过;若是此时有了单元/集成测试,那咱们能很好的解决这些问题。(注:加下来若是没有特殊状况,不刻意强调 单元测试/集成测试,即提到测试是指的是单元/集成测试)php
我从如下几个方面介绍测试:html
一、为何须要测试?java
二、如何进行测试?node
三、测试有哪些好处?python
四、一切都须要测试吗?mysql
测试的目的是什么?个人理解是:git
因此若是你遇到如上问题,就须要写测试。写测试多是为了本身(一、2);也多是为了帮助别人(3)。github
不少朋友不知道如何进行测试,其实测试很简单,别把它想复杂了,按照本身的想法测试每一个功能点是否正确便可。web
单元测试流程
集成测试流程
集成测试流程
能够看出,单元测试与集成测试惟一不一样点是一个调用依赖系统而一个不调用;由于单元测试是最小粒度的测试,如在Java中是测试一个类,不会测试依赖系统;而集成测试是会测试依赖系统的。
测试的步骤:
环境:也叫作夹具(fixture)或者固件,表示调用被测系统时须要准备/清理的数据等等;
被测系统:在Java中就是要测试的类,如UserService;
依赖系统:测试被测系统时,其依赖的部分,如UserDao;
测试用例:包含测试方法的类,里边有不少测试方法来测试被测系统。
接下来仔细看看各部分都作了哪些工做。
环境,也叫作夹具(fixture),表示调用被测系统时须要准备/清理的数据等等;保证测试时环境是干净的,如不被以前的数据库数据影响;保证每次测试都是在干净/新鲜的环境中执行的。所谓干净的环境表示如当前测试不被以前测试插入/删除/修改的数据形成影响。在junit中可使用:
使用如上方法,而不是直接在测试方法中安装/卸载;是由于无论有没有异常,@After/@AfterClass都会执行,这样防止出现异常可能形成环境是不新鲜的问题。
若是你们使用spring test来测试数据库相关的系统,能够考虑使用@TransactionConfiguration来支持默认事务回滚,这样不会对现有系统形成影响。具体可参考《【第十三章】 测试 之 13.1 概述 13.2 单元测试 ——跟我学spring3》和《【第十三章】 测试 之 13.3 集成测试 ——跟我学spring3》
测试时必定要保证环境是干净/新鲜的,才能保证每次测试的结果是同样的。
被测系统:在Java中就是被测试的Java类。
依赖系统:就是被测试Java类依赖的其余类。
若是是单元测试,通常状况下,会对依赖系统进行模拟(Mock),即给它一个假的实现;典型的如测试服务层时注入一个Mock的DAO层,这样的好处:
若是是集成测试时,直接注入真实的依赖系统便可,好处:
单元测试虽然好,可是是隔离测试,即不会调用被测系统来完成测试,由于不是真实的联调,因此极可能会潜在有一些问题,所以仍是须要集成测试。(因此不是很刻意分单元或集成测试,且有些系统可能只有集成测试)
可是集成测试速度是比较慢的,通常提交给CI执行,不影响当前开发进度。
验证的目的:是保证明际结果和咱们预期的结果是否一致,说白了就是是不是咱们想的那样。
通常使用断言来验证,如:
Assert.assertEquals(expectedResult, actualResult); //验证预期结果和实际结果是否相等
验证主要有两种:
结果验证:即验证被测系统返回的结果是否正确,如:
验证返回的数据总数 = 插入以前的总数 + 1; 即结果验证。此处咱们使用了一种叫作相对(delta)测试;即不关心数据库里到底多少条,只关心实际的和预期的差。
行为验证:即验证被测系统是否调用了依赖系统的某个API ,这个只有当咱们使用Mock时测试时比较简单,如当用户注册时:
一、加积分
二、发系统消息
三、……
此时咱们并不能经过结果验证是否调用了这些方法;那么咱们可使用Mock技术来完成验证是否调用了这些API,好比使用jmock测试框架就支持行为验证。集成测试是很难进行行为验证的,若是测试须要预留间谍接口。
咱们写代码的目的是正确的完成某个功能,如何保证正确呢?测试!因此在不使用如单元测试技术时,咱们也是须要测试,可是这个测试是咱们人工验证的。缺点很明显:
为了解决这个问题,咱们使用如单元测试技术来解决这个问题:
即测试的好处,从如上已经提炼出来了:
确定不是,一切都是相对的;哪些不须要测试呢:
你很是熟悉的功能;
一些简单的CRUD;
你认为不须要测试的;好比你颇有把握的东西,就没有必要浪费时间测试了;
哪些须要测试呢:
测试不是不耗时间的,没意义的测试就是浪费时间,最典型是一些书上的对一个增删改查进行测试,实际项目没有任何意义。因此你应该只对本身很难驾驭的以为有必要的代码进行测试。不要成为一个测试狂,什么都测试。
一些测试能够参考个人《es——JavaEE快速开发脚手架》中的代码。经过测试我获得了许多好处。
到此咱们介绍完成了测试,可是若是咱们使用了如集成测试时,测试执行起来可能比较慢,跑一遍测试可能须要5分钟,那怎么办呢?
天天下班前跑一遍集成测试,而后修复,下班走人;
CI:持续集成,交给持续集成服务器,自动地测试完成后把测试报告以邮件的形式发到开发人员邮箱;
------------------------------------分割线----------------------------------
接下来介绍一下CI吧。
一、为何须要CI
二、CI如何工做的
三、travis-ci介绍
正如前边说的,咱们单独测试可能会遇到以下问题:
那怎么办呢?自动化地持续集成(CI)!CI的核心就是干这件事情的。自动化持续地集成测试。
使用CI后,若是使用Maven,能够新建多个profile:
一个典型的持续集成流程:
如图所示:
持续集成服务器其实就是一个定时器,自动帮你下载最新代码、编译、测试、集成及产生报告发给开发人员。
常见的CI服务器有:
我09年时使用过TeamCity社区版,足够知足常见需求;目前我使用github托管项目,使用Travis CI进行分布式的持续集成,免费,目前看来仍是不错的。
我如今开发的ES-JavaEE项目开发脚手架就是使用travis ci进行持续集成;具体参考《Getting started》进行与Github集成,其支持的语言:
支持的数据库:
若是是Java开发人员,支持的JDK包括:OpenJDK 和 OracleJDK。 若是使用的是OpenJDK,Maven中使用ascii2native插件时,须要以下配置:
若是使用mysql,端口只能是3306。
若是想开端口测试,这是不容许的。
以下是我项目中的一个配置.travis.yml,放到项目的根下便可:
-----------------------------------
language: java 语言
env: 环境
- DB=mysql 使用mysql
jdk:
- openjdk jdk使用openjdk
mysql:
database: es 数据库名为es
username: root 用户名为root
password : 密码为空
encoding: utf8 编码为utf8
install: 安装时执行的脚本
- mvn install -Dmaven.test.skip=true mvn安装并跳过测试
before_script: script以前执行的测试
- cd web
- mvn db:create 建立数据库的mvn命令(此处使用了 maven-db-plugin 插件)
- mvn db:schema 建立脚本的mvn命令
- mvn db:data 安装数据的mvn命令
- cd ..
script: 测试时执行的脚步
- cd common
- mvn test 测试common子模块
- cd ..
- cd web
- mvn test -Pit 测试web子模块,并指定使用it profile测试(即集成测试的配置,具体参考pom.xml中的profile/it)
notifications: 触发
email: 测试完成后测试报告发到哪
- zhangkaitao0503@gmail.com
-----------------------------------
持续集成不能修复代码的错误,而是和单元测试同样,缩短发现问题带解决问题的时间,这样能够提升开发效率,下降项目风险,提升项目的稳定性。并且尤为是团队协做时,能够发现其余人的代码是否对本身的代码产生影响。
到此咱们利用单元测试+CI能够加速开发人员的开发速度。利用好单元测试和CI,不要纯粹为了单元测试和CI而去作这些事情。
本文没有介绍TDD,TDD并不会那么美好,我认为咱们能够借鉴TDD的一些思想,但决不能迷信TDD,有时候,尤为如开发企业应用,先写功能再写测试可能效率更高,并且大部分时候是不须要TDD的。并且我也没能在实际项目中获取太多TDD的好处,可是我得到了测试的好处。
本文也没有介绍测试覆盖率,我认为不要一味的追求覆盖率,有时候有的覆盖率没有任何意义。因此不要让为了覆盖率而覆盖率拖慢了项目开发进度。
正如stackoverflow上的一篇帖子《How deep are your unit tests?》上Kent Beck的回答:
能够前往coolshell的“单元测试要作多细?”去获得一些经验。
推荐阅读:
【第十三章】 测试 之 13.1 概述 13.2 单元测试 ——跟我学spring3
【第十三章】 测试 之 13.3 集成测试 ——跟我学spring3
《xUnit测试模式》
《持续集成:软件质量改进和风险下降之道》《持续交付--发布可靠软件的系统方法》