单元测试
1,自动化测试
1.1通过断言的方式来确定结果是否正确Assert
1.2引入junit的jar包 不建议直接使用eclipse中提供的包
1.3创建一个操作类 在src目录下编写服务器代码
1,导入junit的jar,不建议直接使用eclipse中所提供的包
2,在src目录下编写服务代码
3.创建测试类
基本原则 1.在eclipse中创建一个source folder命名为test
2,创建一个测试类所在的包,包的名称和要测试的类一致
4.Junit3和Junit4两者之间区别是非常明显的
在Junit3中,如果某个类需要是测试类,必须将其继承与TestCase,如果某个方法需要是测试方法,必须让这个方法
范通过textxx开头,在Junit3中,如果希望指定某个测试方法运行某个初始方法,这个方法名称必须setUp,如
果希望在某个测试方法运行之后运行某个释放资源的方法,这个方法名称必须testDown
在Junit4中,一个POJO类就是一个测试类,测试方法通过@Test来标识,初始化方法通过@Before,释放资源的方法通过 @After来
标注,但是为了让Junit4中的类在Junit3中可以使用,习惯把初始化方法命名为setUp ,释放资源的方法命名为testDown 测试方法同样以test开头
5, 如果使用断言
hamcrest可以有效增加junit的测试能力,用一些相对通俗的语言来进行测试
要使用junit中的assertThat来进行断言
第一个参数表示实际值,第二个参数表示hamcrest的表达式
特别注意,如果使用junit4.10 必须把hamcrest的jar包移到junit的jar之前,否则,组合条件allOf, anyOf都会抛出异常
TestSuite
可以通过testSuite来组成多个测试组件
正常的开发流程
编码---》测试-》重复--》提交
基于测试驱动的开发
测试-》编写-->重复---》提交
先写了测试之后,由于测试的覆盖率要求为100%,所以就会让代码中可能存在的分支都进行测试,这样先写测试单元,
可以为将来的代码提供了一种有效的参考
cobertura使用
1,将cobertura的路径设置到path中
2,将要测试的源代码,编译之后的字节码文件和所需要的jar包拷贝到一个单独的目录中做处理
3,在命令提示符中使用命令为生成测试覆盖报告的代码生成一个ser的文件
3.1
cobertura-instrument --destination instrumented com/test/junit/
4.基于ser文件运行测试
4.1java -cp lib/junit-4.10.jar;lib/cobertura.jar;.;instrumented;.;-Dnet.sourceforge.cobertura.datafile=cobertura.ser org.junit.runner.JUnitCore org.konghao.manager.TestUsertManager
5.根据ser文件生成测试覆盖率的报告
特别注意:如果文件的编码是utf-8的,在生成报告前需要为coberture-report.bat文件增加DfileEncoding的处理
java -cp "%COBERTURA_HOME%cobertura.jar;%COBERTURA_HOME%lib\asm-3.0.jar;%COBERTURA_HOME%lib\asm-tree-3.0.jar;%COBERTURA_HOME%lib\log4j-1.2.9.jar;%COBERTURA_HOME%lib\jakarta-oro-2.0.8.jar" net.sourceforge.cobertura.reporting.Main %CMD_LINE_ARGS%
黑盒测试
白盒测试
2,基于测试开发的方式和优点
3,stub和mock
mock对象用来测试一些未实现关联对象的类进行测试的对象
mock和stub的区别
mock关注的是交互
stub关注的是状态
EasyMock就是实现mock对象的框架
1,导入easymock的jar包
2,Mock对象的三个生命周期
三个阶段 record replay verify
Mock的关注点是在交互上,注意解决的问题是对象之间的交互,诸如:Service就依赖于DAO,如果DAO没有实现,我们可以通过Mock来模拟DAO的实现
record阶段就是用来说明这个DAO上面可能存在的值
@Test
public void testLoad(){
//1,创建DAO的Mock对象,目前就进入record阶段
IUserDao ud= EasyMock.createMock(IUserDao.class);
User u = new User(1,"admin","123","管理员");
//2,记录ud可能会发生的操作的结果
/*
* 以下代码所指的是,当在dao中调用了load方法并且参数为admin的时候,返回值是u对象
*/
//必须把交互的所有过程记录下来
EasyMock.expect(ud.load("asd")).andReturn(u);
ud.delete("abc");
//以下用来操作没有返回值的方法
EasyMock.expectLastCall();
EasyMock.expect(ud.load("admin")).andReturn(u);
//3进入测试阶段,也就是replay阶段
EasyMock.replay(ud);
//创建Service和DAO的关联
IUserService us = new UserService(ud);
//完成测试
User tu = us.load("admin");
EntitiesHelper.assertUser(tu,u);
//3,验证交互关系是否正确
EasyMock.verify(ud);
}
mock的几种创建方式,
1,createMock
通过createMock所创建的mock对象,在进行verify的时候仅仅只是检查关联方法是否正确完成调用,如果完成次数一致
就认为测试通过,不考虑顺序问题
public void testLoadMock(){
//创建DAO的对象,目前就进入record阶段
IUserDao ud = EasyMock.createMock(IUserDao.class);
User u = new User(1,"admin","123","管理员");
EasyMock.expect(ud.load("asd")).andReturn(u);
//使用的CreateMock,如果方法的调用顺不一致,不会抛出异常
ud.delete("abc");
EasyMock.expectLastCall();
EasyMock.expect(ud.load("admin")).andReturn(u);
EasyMock.replay(ud);
//创建Service和Dao关联
IUserService us = new UserService(ud);
//完成测试
User tu = us.load("admin");
EntitiesHelper.assertUser(tu,u);
//验证交互关系是否正确
EasyMock.verify(ud);
}
2,createSrtictMock
在verify时不仅仅验证关联方法的调用此时还要验证顺序
public void testLoadStrictMock(){
//创建DAO的Mock对象,目前就进去了record阶段
IUserDao ud = EasyMock.createStrictMock(IUserDao.class);
User u = new User(1,"admin","123","管理员");
EasyMock.expect(ud.load("asd")).andReturn(u);
//使用的CreateStrictMock,方法的顺序不一致,所以会抛出异常
ud.delete("abc");
EasyMock.expectLastCall();
EasyMock.expect(ud.load("admin")).andReturn(u);
EasyMock.replay(ud);
//关系serviceDao
IUserService us = new UserService(ud);
//完成测试
User tu = us.load("admin");
EntitiesHelper.assertUser(tu,u);
//3,验证交互关系是否正确
EasyMock.verify(ud);
}
4,在容器中测试
4.1,jetty
4.2 cactus 可以完成模拟J2EE的容器测试
可以测试servlet jsp filter 和EJB
cactus注意是基于junit3.8来进行操作的,并不支持junit4中的annotaion
搭建环境
导入包 aspectjrt-1.5.3.jar
cactus.core.framework.uberjar.javaEE.14-1.8.1.jar
cactus.integration.ant-1.8.1.jar
cactus.integration.shared.api-1.8.1.jar
commons-discovery-0.4.jar
commons-httpclient-3.1.jar
commons-logging-1.1.jar
geronimo-j2ee-management_1.0_spec-1.1.jar
httpunit-1.6.jar
servlet-api-2.4.jar
org.mortbay.jetty-5.1.9.jar
commons-codec-1.7.jar
cargo-core-uberjar-1.0-beta-2.jar
cargo-core-container-jonas-1.0-beta-2.jar
创建servlet的测试类
5.dbUnit
dbunit具体隔离数据库的访问,
1导入jar包
dbunit.jar
slf4j.jar(一定使用1.6的版本)
2,创建dbunit的测试数据xml文件
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<!-- <t_user>
<id>1</id>
<username>kh</username>
<password>123</password>
<nickname>孔浩</nickname>
</t_user>-->
<t_user id="1" username="admin" password="123" nickname="超级管理员"></t_user>
</dataset>
3,创建dbunit的Connection
dbunit的connection是用来对数据文件进行操作的,这个connection必须依赖于目前项目中所使用的connection
IDatabaseConnection com = new DatabaseConnection(DbUtil.getConnection());
4.创建IDdataSet,通过DATASET来获取测试数据
/**
* FlatXmlDataSet 用来获取基于属性存储的属性值
* XMLDateSet用来获取基于节点类型存储的属性值
*/
IDataSet ds = new FlatXmlDataSet(
new FlatXmlProducer(
new InputSource(
TestDbUnit.class.getClassLoader().getResourceAsStream("t_user.xml"))));
5.初始化数据并且完成测试
//从DAO中获取数据并且完成测试
IUserDao ud = new UserDao();
User tu = ud.load("admin");
assertEquals(tu.getId(), 1);
assertEquals(tu.getUsername(), "admin");
assertEquals(tu.getPassword(), "123");
assertEquals(tu.getNickname(), "超级管理员");
6. 备份
@Test
public void testBackup(){
//超级dbunit的Connection 需要插入一个数据的connection作为参数
try {
DatabaseConnection con = new DatabaseConnection(DbUtil.getConnection());
//根据con创建相应的dataset,这个dataset包含了所有表
IDataSet ds = con.createDataSet();
//将ds中的数据通过FlatXmlDataSet的格式写到文件中
FlatXmlDataSet.write(ds, new FileWriter("D:/android_app/junit/junit01/test.xml"));
} catch (DatabaseUnitException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
以上演示的是备份数据库的所有文件
备份某些特定的表
@Test
public void testBackUpTable(){
try {
//创建dbunit的Connection ,需要传入一个数据库的connection作为参数
IDatabaseConnection con = new DatabaseConnection(DbUtil.getConnection());
//通过QueryDataSet可以有效的选择要处理的表来作为数据集
QueryDataSet backup = new QueryDataSet(con);
//添加t_user这张表作为备份表
backup.addTable("t_user");
FlatXmlDataSet.write(backup, new FileWriter("D:/android_app/junit/junit01/test1.xml"));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DatabaseUnitException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
1,自动化测试
1.1通过断言的方式来确定结果是否正确Assert
1.2引入junit的jar包 不建议直接使用eclipse中提供的包
1.3创建一个操作类 在src目录下编写服务器代码
1,导入junit的jar,不建议直接使用eclipse中所提供的包
2,在src目录下编写服务代码
3.创建测试类
基本原则 1.在eclipse中创建一个source folder命名为test
2,创建一个测试类所在的包,包的名称和要测试的类一致
4.Junit3和Junit4两者之间区别是非常明显的
在Junit3中,如果某个类需要是测试类,必须将其继承与TestCase,如果某个方法需要是测试方法,必须让这个方法
范通过textxx开头,在Junit3中,如果希望指定某个测试方法运行某个初始方法,这个方法名称必须setUp,如
果希望在某个测试方法运行之后运行某个释放资源的方法,这个方法名称必须testDown
在Junit4中,一个POJO类就是一个测试类,测试方法通过@Test来标识,初始化方法通过@Before,释放资源的方法通过 @After来
标注,但是为了让Junit4中的类在Junit3中可以使用,习惯把初始化方法命名为setUp ,释放资源的方法命名为testDown 测试方法同样以test开头
5, 如果使用断言
hamcrest可以有效增加junit的测试能力,用一些相对通俗的语言来进行测试
要使用junit中的assertThat来进行断言
第一个参数表示实际值,第二个参数表示hamcrest的表达式
特别注意,如果使用junit4.10 必须把hamcrest的jar包移到junit的jar之前,否则,组合条件allOf, anyOf都会抛出异常
TestSuite
可以通过testSuite来组成多个测试组件
正常的开发流程
编码---》测试-》重复--》提交
基于测试驱动的开发
测试-》编写-->重复---》提交
先写了测试之后,由于测试的覆盖率要求为100%,所以就会让代码中可能存在的分支都进行测试,这样先写测试单元,
可以为将来的代码提供了一种有效的参考
cobertura使用
1,将cobertura的路径设置到path中
2,将要测试的源代码,编译之后的字节码文件和所需要的jar包拷贝到一个单独的目录中做处理
3,在命令提示符中使用命令为生成测试覆盖报告的代码生成一个ser的文件
3.1
cobertura-instrument --destination instrumented com/test/junit/
4.基于ser文件运行测试
4.1java -cp lib/junit-4.10.jar;lib/cobertura.jar;.;instrumented;.;-Dnet.sourceforge.cobertura.datafile=cobertura.ser org.junit.runner.JUnitCore org.konghao.manager.TestUsertManager
5.根据ser文件生成测试覆盖率的报告
特别注意:如果文件的编码是utf-8的,在生成报告前需要为coberture-report.bat文件增加DfileEncoding的处理
java -cp "%COBERTURA_HOME%cobertura.jar;%COBERTURA_HOME%lib\asm-3.0.jar;%COBERTURA_HOME%lib\asm-tree-3.0.jar;%COBERTURA_HOME%lib\log4j-1.2.9.jar;%COBERTURA_HOME%lib\jakarta-oro-2.0.8.jar" net.sourceforge.cobertura.reporting.Main %CMD_LINE_ARGS%
黑盒测试
白盒测试
2,基于测试开发的方式和优点
3,stub和mock
mock对象用来测试一些未实现关联对象的类进行测试的对象
mock和stub的区别
mock关注的是交互
stub关注的是状态
EasyMock就是实现mock对象的框架
1,导入easymock的jar包
2,Mock对象的三个生命周期
三个阶段 record replay verify
Mock的关注点是在交互上,注意解决的问题是对象之间的交互,诸如:Service就依赖于DAO,如果DAO没有实现,我们可以通过Mock来模拟DAO的实现
record阶段就是用来说明这个DAO上面可能存在的值
@Test
public void testLoad(){
//1,创建DAO的Mock对象,目前就进入record阶段
IUserDao ud= EasyMock.createMock(IUserDao.class);
User u = new User(1,"admin","123","管理员");
//2,记录ud可能会发生的操作的结果
/*
* 以下代码所指的是,当在dao中调用了load方法并且参数为admin的时候,返回值是u对象
*/
//必须把交互的所有过程记录下来
EasyMock.expect(ud.load("asd")).andReturn(u);
ud.delete("abc");
//以下用来操作没有返回值的方法
EasyMock.expectLastCall();
EasyMock.expect(ud.load("admin")).andReturn(u);
//3进入测试阶段,也就是replay阶段
EasyMock.replay(ud);
//创建Service和DAO的关联
IUserService us = new UserService(ud);
//完成测试
User tu = us.load("admin");
EntitiesHelper.assertUser(tu,u);
//3,验证交互关系是否正确
EasyMock.verify(ud);
}
mock的几种创建方式,
1,createMock
通过createMock所创建的mock对象,在进行verify的时候仅仅只是检查关联方法是否正确完成调用,如果完成次数一致
就认为测试通过,不考虑顺序问题
public void testLoadMock(){
//创建DAO的对象,目前就进入record阶段
IUserDao ud = EasyMock.createMock(IUserDao.class);
User u = new User(1,"admin","123","管理员");
EasyMock.expect(ud.load("asd")).andReturn(u);
//使用的CreateMock,如果方法的调用顺不一致,不会抛出异常
ud.delete("abc");
EasyMock.expectLastCall();
EasyMock.expect(ud.load("admin")).andReturn(u);
EasyMock.replay(ud);
//创建Service和Dao关联
IUserService us = new UserService(ud);
//完成测试
User tu = us.load("admin");
EntitiesHelper.assertUser(tu,u);
//验证交互关系是否正确
EasyMock.verify(ud);
}
2,createSrtictMock
在verify时不仅仅验证关联方法的调用此时还要验证顺序
public void testLoadStrictMock(){
//创建DAO的Mock对象,目前就进去了record阶段
IUserDao ud = EasyMock.createStrictMock(IUserDao.class);
User u = new User(1,"admin","123","管理员");
EasyMock.expect(ud.load("asd")).andReturn(u);
//使用的CreateStrictMock,方法的顺序不一致,所以会抛出异常
ud.delete("abc");
EasyMock.expectLastCall();
EasyMock.expect(ud.load("admin")).andReturn(u);
EasyMock.replay(ud);
//关系serviceDao
IUserService us = new UserService(ud);
//完成测试
User tu = us.load("admin");
EntitiesHelper.assertUser(tu,u);
//3,验证交互关系是否正确
EasyMock.verify(ud);
}
4,在容器中测试
4.1,jetty
4.2 cactus 可以完成模拟J2EE的容器测试
可以测试servlet jsp filter 和EJB
cactus注意是基于junit3.8来进行操作的,并不支持junit4中的annotaion
搭建环境
导入包 aspectjrt-1.5.3.jar
cactus.core.framework.uberjar.javaEE.14-1.8.1.jar
cactus.integration.ant-1.8.1.jar
cactus.integration.shared.api-1.8.1.jar
commons-discovery-0.4.jar
commons-httpclient-3.1.jar
commons-logging-1.1.jar
geronimo-j2ee-management_1.0_spec-1.1.jar
httpunit-1.6.jar
servlet-api-2.4.jar
org.mortbay.jetty-5.1.9.jar
commons-codec-1.7.jar
cargo-core-uberjar-1.0-beta-2.jar
cargo-core-container-jonas-1.0-beta-2.jar
创建servlet的测试类
5.dbUnit
dbunit具体隔离数据库的访问,
1导入jar包
dbunit.jar
slf4j.jar(一定使用1.6的版本)
2,创建dbunit的测试数据xml文件
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<!-- <t_user>
<id>1</id>
<username>kh</username>
<password>123</password>
<nickname>孔浩</nickname>
</t_user>-->
<t_user id="1" username="admin" password="123" nickname="超级管理员"></t_user>
</dataset>
3,创建dbunit的Connection
dbunit的connection是用来对数据文件进行操作的,这个connection必须依赖于目前项目中所使用的connection
IDatabaseConnection com = new DatabaseConnection(DbUtil.getConnection());
4.创建IDdataSet,通过DATASET来获取测试数据
/**
* FlatXmlDataSet 用来获取基于属性存储的属性值
* XMLDateSet用来获取基于节点类型存储的属性值
*/
IDataSet ds = new FlatXmlDataSet(
new FlatXmlProducer(
new InputSource(
TestDbUnit.class.getClassLoader().getResourceAsStream("t_user.xml"))));
5.初始化数据并且完成测试
//从DAO中获取数据并且完成测试
IUserDao ud = new UserDao();
User tu = ud.load("admin");
assertEquals(tu.getId(), 1);
assertEquals(tu.getUsername(), "admin");
assertEquals(tu.getPassword(), "123");
assertEquals(tu.getNickname(), "超级管理员");
6. 备份
@Test
public void testBackup(){
//超级dbunit的Connection 需要插入一个数据的connection作为参数
try {
DatabaseConnection con = new DatabaseConnection(DbUtil.getConnection());
//根据con创建相应的dataset,这个dataset包含了所有表
IDataSet ds = con.createDataSet();
//将ds中的数据通过FlatXmlDataSet的格式写到文件中
FlatXmlDataSet.write(ds, new FileWriter("D:/android_app/junit/junit01/test.xml"));
} catch (DatabaseUnitException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
以上演示的是备份数据库的所有文件
备份某些特定的表
@Test
public void testBackUpTable(){
try {
//创建dbunit的Connection ,需要传入一个数据库的connection作为参数
IDatabaseConnection con = new DatabaseConnection(DbUtil.getConnection());
//通过QueryDataSet可以有效的选择要处理的表来作为数据集
QueryDataSet backup = new QueryDataSet(con);
//添加t_user这张表作为备份表
backup.addTable("t_user");
FlatXmlDataSet.write(backup, new FileWriter("D:/android_app/junit/junit01/test1.xml"));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DatabaseUnitException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}