Mais conteúdo relacionado Semelhante a Java与单元测试.ppt (20) Java与单元测试.ppt11. JUnit 基础知识
testxxx fixture assert bar
继承了
testcase
测试类的
一个方法,
相当于一
个测试用
例
调用每个
testxxx()
前后固定执
行的环境搭
建和拆除函
数(testcase
调用顺序不
定导致)
检验expect
和actual是
否匹配的系
列函数;通过
assert检验
的用例被认
为是成功的,
否则就认为
是失败
Eclipse“Ru
n as JUnit”
执行测试用例,
符合assert表
示成功(显示
绿条)、否则
为失败(蓝条)、
程序抛异常会
报错(红条)
13. JUnit 3.x 示例
public class Junit3 extends TestCase{
protected void setUp() {
super.setUp(); //fixture
}
public void testMul(){
double ret = cal.mul(12.5, 2.0);
//assert语句:谓(Equals)+主(ret)+宾(25.0)
assertEquals(ret, 25.0);
}
}
16. Junit 4 示例
public class junit4 {
private static multiple cal;
@BeforeClass
public static void globalInit(){
cal = new multiple();
}
@Before public void init(){
System.out.println("init");
}
@Test public void simpleTest(){
int result = cal.mul_int(3, 5);
assertThat(result, is(15));
}
}
23. 参数测试示例
@RunWith(Parameterized.class)
public class parameterTest {
private int n1, n2, result;
public parameterTest(int para1, int para2, int result){
this.n1 = para1;
this.n2 = para2;
this.result = result;
}
@Parameters public static Collection parameters(){
return Arrays.asList(new Object[][]{
{1,2,3},
{2,3,5},
{3,4,7} });
}
@Test public void testAddWithPara(){
calculator cal = new calculator();
int ret = cal.add(n1, n2);
assertEquals(result, ret);
}
}
30. DBUnit框架基类
DatabaseTestCase
测试类extends的基类
子类必须实现getDataSet() 指定预置数据
子类必须实现getConnection()指定数据库
(driver、url、username、password)
子类可以覆盖getSetUpOperation()指定初始
化操作,缺省是CLEAN_INSERT
子类可以覆盖getTearDownOperation (),缺
省是NONE
以test开头的方法识别为测试用例:获取预期
数据和实际数据,并进行对比
31. DBUnit核心对象-数据集
IDataSet
‘I’开头的对象表示接口
本测试流程所关注的数据集合
重要实现FlatXmlDataSet(xml文件数据集)
由ITable对象组成,通过getTable(String
tblname)、getTables()获取。
getTableMetaData getTable(String tblname)获
取table的描述信息
用filter进行过虑:IColumnFilter
(DefaultColumnFilter . includeColumns
/excludeColumns )、ITableFilter
(DefaultTableFilter .includeTable/excludeTable)
32. DBUnit核心对象-数据库连接
IDatabaseConnection
DBUnit对普通数据库连接的简单封装
两个实现:DatabaseConnection(针对jdbc)、
DatabaseDataSourceConnection
普遍用法
两个方法:
createDataSet()/createDataSet (String[] )
createQueryTable(String resultTbl,String sql)
相关对象:
QueryDataSet (IDatabaseConnection conn)
QueryDataSet.addTable(resultTbl, sql);
protected IDatabaseConnection getConnection() throws Exception
{
Class.forName(dbDriver);
Connection con = DriverManager.getConnection(dbUrl, dbUsername,
dbPassword);
return new DatabaseConnection(con);
}
34. DBUnit核心对象-数据对比
assertion
assertEquals(expectedDataSet, actualDataSet)
assertEquals(expectedTable, actualTable)
assertEquals(expected, actual, FailureHandler)
DiffCollectingFailureHandler myHandler;
List diffList = myHandler.getDiffList();
Difference diff = (Difference)diffList.get(i);
diff.getActualTable()/getExpectedTable()
diff.getActualValue()/getExpectedValue()
diff.getColumnName()
36. 从数据库导出 xml文件实例
public boolean generateXML() {
Connection con = null;
try
{
Class.forName(dbDriver); //传统jdbc连接
con = DriverManager.getConnection(dbUrl,
dbUsername, dbPassword);
//返回DBUnit封装的数据库连接
IDatabaseConnection conn = new
DatabaseConnection(con);
String tables[]={"ut_userRings",
"ut_chargeLog"};
IDataSet dataSet =
conn.createDataSet(tables);
FlatXmlDataSet.write(dataSet, new
FileOutputStream("xml/dbunit.xml"));
}
……
}
37. 两种xml格式文件
<?xml version='1.0' encoding='UTF-
8'?>
<dataset>
<table name="UNITTEST">
<column>userindex</column>
<column>phonenumber</column>
<column>createDate</column>
<column>loginName</column>
<column>passwd</column>
<column>account</column>
<row>
<value>1</value>
<value>13812345678</value>
<value>2008-10-10</value>
<value>EB</value>
<value>123456</value>
<value>50.0</value>
</row>
</table>
</dataset>
xml文件
<?xml version='1.0'
encoding='UTF-8'?>
<dataset>
<UNITTEST userindex="1"
phonenumber="13812345678"
createDate="2008-10-10"
loginName="EB"
passwd="123456"
account="50.0"/>
<UNITTEST userindex="2"
phonenumber="13500008888"
createDate="2008-10-21"
loginName="9527"
passwd="123456"
account="200.0"/>
</dataset>
XmlDataSet(易抛异常) FlatXmlDataSet(推荐)
42. 2.4.x中定制错误处理
错误:assertEquals失败
出错后代码继续执行,可让所有testxxx都完成运行
每次使用都登记:不抛异常,把所有difference都装入
myHandler,可依次取出记录日志
DiffCollectingFailureHandler myHandler=new …();
Assertion.assertEquals(expect, actual, myHandler);
List diffList = myHandler.getDiffList();
for(int i=0; i<diffList.size(); i++){
Difference diff = (Difference)diffList.get(i);
log(diff.getActualTable()+diff.getColumnName() +
diff.getActualValue();
}
47. Mock object功能说明
依赖关系 期望结果 系统环境 协作软件
模拟数据
库连接、
网络连接
代替真正
的连接
eg.验证
JDBC连接
在使用结束
后关闭(在特
定时刻调用
java.sql.Co
nnection 中
的 close )
eg.模拟
JDBC驱动
程序抛出
的
SQLExce
ption 类
尚未开发完
成的协作模
块,提供接
口定义,检
查是否按规
定的次数和
参数调用了
指定方法
51. JMock测试示例
@RunWith(JMock.class)
public class OpenAccountTest{
static Mockery context;
@BeforeClass public static
void setUpBeforeClass(){
context = new Unit4Mockery(){{ }};
}
@Test
public void openAccountWithMock(){
final SMS recv= context.mock(SMS.class)
context.checking(new Expectations(){{
one(recv).getReplyFromUser(with(equal(phoneNumber)));
will(returnValue("Y"));
}});
account.openAccount(phoneNumber, recv);
}
57. Expectation参数(3)
sequence按次序执行
final sequence seq=context.sequence(“name”)
one(amock).forward(10);inSequence(seq);
one(amock).turn(45);inSequence(seq);
state-machine按时序执行
final States st =
context.states(“name”).startsAs(“up”);
one(amock).forward(10); when(st.is( “up”));
one(amock).turn(45); then(st.is(“down”));
58. JMock测试Generic Type
Java的Dynamic Reflection不能与
Generic Type无缝配合
mock如下对象:
public interface Juicer<T extends Fruit>{
Liquid juice(T fruit); }
报错写法:Juicer<Orange> orangeJuicer =
context.mock(Juicer<Orange>.class,"orange");
告警写法:Juicer<Orange> orangeJuicer =
(Juicer<Orange>)context.mock(Juicer.class,
“orange”);
可用@SuppressWarnings去除warning
61. Mock可能导致的问题
掩盖 滥用 脆弱 混乱
可能隐藏所
mock的协
作软件中的
缺陷和错误,
集成测试必
不可少
为了能使用
mock测试
可能会导致
滥用
Interface,
只有1个
implement
的interface
是不提倡的
属于白盒测
试,要非常
熟悉类的内
部联系,对
方法的合理
修改可能破
坏mock测试
可能给测试
代码带来混
乱,最好使
用mock的地
方都加上注
释,如果协作
软件完成了
开发可以替
换mock部分