如何使用JUnit进行自动化测试.docx
- 文档编号:25147914
- 上传时间:2023-06-05
- 格式:DOCX
- 页数:22
- 大小:413.67KB
如何使用JUnit进行自动化测试.docx
《如何使用JUnit进行自动化测试.docx》由会员分享,可在线阅读,更多相关《如何使用JUnit进行自动化测试.docx(22页珍藏版)》请在冰豆网上搜索。
如何使用JUnit进行自动化测试
如何使用JUnit进行自动化测试
1如何利用JUnit在Eclipse中开发自动化脚本
JUnit可以和很多开发工具进行集成来进行单元测试,我们这里选取较常用的java开发工具Eclipse来使用JUnit4进行单元测试。
如何在开发工具Eclipse里 进行单元测试
首先新建一个项目叫JUnit_Test,我们编写一个Calculator类,这是一个能够简单实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试。
这个类并不是很完美,我们故意保留了一些Bug用于演示,这些Bug在注释中都有说明。
该类代码如下:
packageandycpp;
publicclassCalculator
{
privatestaticintresult;//静态变量,用于存储运行结果
publicvoidadd(intn)
{
result=result+n;
}
publicvoidsubstract(intn)
{
result=result-1;//Bug:
正确的应该是result=result-n
}
publicvoidmultiply(intn)
{
}//此方法尚未写好
publicvoiddivide(intn)
{
result=result/n;
}
publicvoidsquare(intn)
{
result=n*n;
}
publicvoidsquareRoot(intn)
{
for(;;);//Bug:
死循环
}
publicvoidclear()
{//将结果清零
result=0;
}
publicintgetResult()
{
returnresult;
}
}
第二步,将JUnit4单元测试包引入这个项目:
在该项目上点右键,点“属性”,如图:
在弹出的属性窗口中,首先在左边选择“JavaBuildPath”,然后到右上选择“Libraries”标签,之后在最右边点击“AddLibrary…”按钮,如下图所示:
然后在新弹出的对话框中选择JUnit4并点击确定,如上图所示,JUnit4软件包就被包含进我们这个项目了。
第三步,生成JUnit测试框架:
在Eclipse的PackageExplorer中用右键点击该类弹出菜单,选择“NewJUnitTestCase”。
如下图所示:
在弹出的对话框中,进行相应的选择,如下图所示:
点击“下一步”后,系统会自动列出你这个类中包含的方法,选择你要进行测试的方法。
此例中,我们仅对“加、减、乘、除”四个方法进行测试。
如下图所示:
之后系统会自动生成一个新类CalculatorTest,里面包含一些空的测试用例。
你只需要将这些测试用例稍作修改即可使用。
完整的CalculatorTest代码如下:
packageandycpp;
importstaticorg.junit.Assert.*;
importorg.junit.Before;
importorg.junit.Ignore;
importorg.junit.Test;
publicclassCalculatorTest
{
privatestaticCalculatorcalculator=newCalculator();
@Before
publicvoidsetUp()throwsException
{
calculator.clear();
}
@Test
publicvoidtestAdd()
{
calculator.add
(2);
calculator.add(3);
assertEquals(5,calculator.getResult());
}
@Test
publicvoidtestSubstract()
{
calculator.add(10);
calculator.substract
(2);
assertEquals(8,calculator.getResult());
}
@Ignore("Multiply()Notyetimplemented")
@Test
publicvoidtestMultiply()
{
}
@Test
publicvoidtestDivide()
{
calculator.add(8);
calculator.divide
(2);
assertEquals(4,calculator.getResult());
}
}
第四步,运行测试代码:
按照上述代码修改完毕后,我们在CalculatorTest类上点右键,选择“RunAsàJUnitTest”来运行我们的测试,如下图所示:
运行结果如下:
进度条是红颜色表示发现错误,具体的测试结果在进度条上面有表示“共进行了4个测试,其中1个测试被忽略,一个测试失败”
2JUnit重要元素
@TEST
方法的前面使用@Test标注,以表明这是一个测试方法。
对于方法的声明也有如下要求:
名字可以随便取,没有任何限制,但是返回值必须为void,而且不能有任何参数。
@Test
publicvoidtestAdd()
{
calculator.add
(2);
calculator.add(3);
assertEquals(5,calculator.getResult());
}
@Before
方法的前面使用@Before标注,表示该测试类中,所有的测试方法在执行前,都会运行该方法。
@After
方法的前面使用@After标注,表示该测试类中,所有的测试方法在执行结束,都会运行该方法。
@BeforeClass
方法的前面使用@BeforeClass标注,表示该测试类首先会执行该方法。
@AfterClass
方法的前面使用@AfterClass标注,表示该测试类所有测试方法执行结束后,执行该方法。
@Ignore
函数的前面加上@Ignore标注,这个标注的含义就是“某些方法尚未完成,暂不参与此次测试”。
这样的话测试结果就会提示你有几个测试被忽略,而不是失败。
一旦你完成了相应函数,只需要把@Ignore标注删去,就可以进行正常的测试。
3如何结合EasyMock去写单元测试
EasyMock主要是起到分层测试的作用,即我不关心哪一层,那一层就可以用mock的方法,把它虚拟出来一个对象,而不真的去创建这个对象。
为了说明EasyMock作用和用法,我们选取自动化测试COE中提供的demo作为例子。
我们选取其中的两个类CalculateService类和CalculateModel类,由于是以面向接口编程的思想开发的代码,所以这两个类之间是通过接口建立起关系的。
这两个类的关系如下图
3.1简单的单元测试写法
CalculateService类的代码如下
packageservice;
importjavax.script.ScriptEngine;
importjavax.script.ScriptEngineManager;
importjavax.script.ScriptException;
publicclassCalculateServiceimplementsICalculateService
{
@Override
publicStringcalculate(Stringtext)
{
ScriptEnginejse=newScriptEngineManager().getEngineByName("JavaScript");
if(null!
=text)
{
try
{
Objectvalue=jse.eval(text);
if(value!
=null)
{
returnString.valueOf(value);
}
}catch(ScriptExceptione)
{
e.printStackTrace();
}
}
return"failed";
}
}
我们先看一下CalculateService的单元测试如何写?
第一步要测试这个类,那我们首先要创建一个这样的对象
代码如下:
@Before
publicvoidsetUp()
{
CalculateServiceservice=newCalculateService();
}
使用Before标签还是BeforeClass的决定条件在于,你要测试的方法是不是每次都要重新创建一个service
第二步明确要测试的方法,并根据要测试的方法,分析测试所需要覆盖的场景。
1.我们要测的方法为calculate;
2.该方法需要覆盖的场景为:
1)输入参数text为null
2)过程中value是null(这种情况的话,输入参数为”null”)
3)运算中出现异常
4)运算正常输出结果
那我们针对这几个场景,写测试代码如下:
@Test
publicvoidshould_return_failed_when_input_is_null()
{
assertEquals("failed",service.calculate(null));
}
@Test
publicvoidshould_return_failed_when_input_is_string_null()
{
assertEquals("failed",service.calculate("null"));
}
@Test
publicvoidshould_return_failed_when_input_is_not_can_calculate()
{
assertEquals("failed",service.calculate("/+*1"));
}
@Test
publicvoidshould_return_5_when_input_is_1_and_4()
{
assertEquals("5.0",service.calculate("1+4"));
}
通过调用service类的calculate方法,并给予不同的输入参数以创建不同的场景,从而验证当前方法是否正确。
上面就是CalculateService的单元测试,那我们下面看下CalculateModel类,并一起来写一下他的单元测试要如何去写?
CalculateModel类的代码如下:
packagemodel;
importservice.ICalculateService;
publicclassCalculateModelimplementsICalculateModel
{
privateICalculateServiceservice;
publicCalculateModel(ICalculateServiceservice)
{
this.service=service;
}
@Override
publicStringcalculate(Stringtext)
{
returnservice.calculate(text);
}
}
我们可以按照上面的步骤去写测试类
第一步创建要测试的对象,这里由于CalculateModel的创建依赖于CalculateService,所以我们要先创建CalculateService;
代码如下:
@Before
publicvoidsetUp()
{
CalculateServiceservice=newCalculateService();
CalculateModelmodel=newCalculateModel(service);
}
第二步明确要测试的方法,并根据要测试的方法,分析测试所需要覆盖的场景。
1.我们要测的方法为calculate;
2、根据代码我们可以看出该方法需要覆盖的场景只有一个,就是不论输入的参数如何,也不管运算的结果是什么,只要调用了CalculateService的calculate方法,并把结果返回出去即可。
测试代码如下:
@Test
publicvoidshould_return_2_when_input_is_1_multiply_2()
{
Stringtext="1*2";
assertEquals("2",model.calculate(text));
}
粗略一看好像没什么问题,但是我们仔细想一下,如果CalculateService的calculate方法出错的话,那么这个测试用例就会报错,因为返回结果就会发生错误。
也就是说我们现在在测CalculateModel,但我们同时还要保证CalculateService的正确,这样显然是有问题的,因为CalculateService不是我们这次测试的对象,它在别的测试类中已经覆盖过了。
那么如何解决这个问题呢?
3.2结合EasyMock的单元测试写法
下面我们用EasyMock来写这个测试用例。
首先,因为我们对CalculateService不关心,所以我们用EasyMock来Mock一个CalculateService。
@Before
publicvoidsetUp()
{
CalculateServiceservice=createMock(ICalculateService.class);
CalculateModelmodel=newCalculateModel(service);
}
然后我们重新用EasyMock的方式来编写这个测试方法,
由于CalculateService是被mock出来的,而非真正的创建这么一个对象,所以对象的方法不会真的运行,所以需要期待调用一下,同时这个方法拥有一个返回值,所以需要我们给它指定一个我们希望的返回值。
(如果后面的方法需要依赖这个返回值作为判断执行的条件,如”if(a==0){}”那么我们这个返回值“a”就需要根据我们希望测试的场景来给指定)
然后我们需要replay一下这个mock对象,以激活它,
最后再在程序的结尾verify一下,来验证它的调用是否和我们期待的一致。
@Test
publicvoidshould_return_2_when_input_is_1_multiply_2()
{
Stringtext="1*2";
expect(service.calculate(text)).andReturn("2");
replay(service);
assertEquals("2",model.calculate(text));
verify(service);
}
总结一下,EasyMock进行单元测试的过程大致可以划分为以下几个步骤:
1、使用EasyMock生成Mock对象;
2、设定Mock对象的预期行为和输出;
3、将Mock对象切换到Replay状态;
4、调用Mock对象方法进行单元测试;
5、对Mock对象的行为进行验证。
3.3元素
这里我们仅介绍我们在自动化测试中会用到的元素,对于其它元素大家可以参考EasyMock官网c:
\iknow\docshare\data\cur_work\
createMock
这个方法的作用是Mock一个我们不希望实际创建的对象。
这个方法有好几个重载方法,我们最常用的是一个参数的,这个参数为我们要Mock对像的类型如:
ICalculateServiceservice=createMock(ICalculateService.class);
expect
这个方法是期待调用Mock对象带返回值的方法。
它的后面通常需要and…方法来指明它执行的结果。
expectLastCall
Mock对象没有返回值的方法,只需要在测试中直接录制这个方法即可,不需要用expect去期待它执行。
但有的时候,我们可能会期望它会有一个异常抛出,或着指定它要执行多少次这个时候,我们就需要用到expectLastCall方法,这个方法的用法如下:
service.noReturnMethod();
expectLastCall().andThrow(newException("异常"));
表明在执行Mock对象service的noReturnMethod方法时,期望它向外抛出一个异常。
andReturn
期望该方法的返回值,参数为Object
andThrow
期望该方法抛出一个异常,参数为Throwable
andAnswer
期望该方法返回一个值或抛出一个异常,这个过程可以通过一段程序来进行。
如:
expect(service.calculate(“2”)).andAnswer(newIAnswer
{
@Override
publicStringanswer()throwsThrowable
{
return2*5*3;
}
});
andDelegateTo
用法和andAnswer()方法类似,但需要建立一个类,这个类要实现Mock对象的接口,用法如下:
public class ServiceStub implements Service {
public int execute(int count) {
return count * 2;
}
}
@Test
public void testRuntimeReturn() {
Business business = new Business();
Service service = EasyMock.createMock(Service.class);
business.setService(service);
EasyMock.expect(service.execute(EasyMock.anyInt())).andDelegateTo(new ServiceStub());
EasyMock.replay(service);
business.execute();
EasyMock.verify(service);
}
any
这里面包括anyBean(),anyByte(),anyChar(),anyInt(),anyLong(),anyFloat(),anyDouble(),anyShort(),
anyObject(),anyString();
用法:
当期待执行的mock方法参数值不确定时,可以根据参数的类型来模拟。
如:
expect(service.calculate(anyString())).andReturn("2");
times
用来指定某一方法执行的次数,如果次数不确定那么可以用anyTimes方法。
expect(service.calculate("1*2")).andReturn("2").times
(2);表明期望该方法执行两次
expect(service.calculate("1*2")).andReturn("2").anyTimes();表明期望该方法执行若干次。
isA
用法:
当期待执行的mock方法参数值为一个对象,并且不确定具体对象时,可以根据参数的类型来模拟。
如:
expect(service.calculate(isA(String.class))).andReturn("2");
isNull
用法:
当期待执行的mock方法参数值为null时,用该方法来声明。
expect(service.calculate(isNull())).andReturn("2");
notNull
用法:
当期待执行的mock方法参数值不为null时,用该方法来声明。
expect(service.calculate(notNull())).andReturn("2");
startWith
用来模糊表达一个值,指明这个值以某个字符串开始。
expect(service.calculate(startWith("1"))).andReturn("2");
endWith
用来模糊表达一个值,指明这个值以某个字符串开始
expect(service.calculate(endWith("2"))).andReturn("2");
matches
用来模糊表达一个值,指明这个值以符合某一正则限定的格式
expect(service.calculate(matches("[1-9][0-9]\{4,\}"))).andReturn("2");
replay
在生成Mock对象和设定Mock对象行为两个阶段,Mock对象的状态都是Record。
在这个阶段,Mock对象会记录用户对预期行为和输出的设定。
在使用Mock对象进行实际的测试前,我们需要将Mock对象的状态切换为Replay。
在Replay状态,Mock对象能够根据设定对特定的方法调用做出预期的响应。
replay(service);
Verify
在利用Mock对象进行实际的测试过程之后,为了验证指定的方法调用真的完成了,我们需要调用verify方法进行验证。
verify(service);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 如何 使用 JUnit 进行 自动化 测试