JUnit使用方法以及测试代码覆盖率.docx
《JUnit使用方法以及测试代码覆盖率.docx》由会员分享,可在线阅读,更多相关《JUnit使用方法以及测试代码覆盖率.docx(14页珍藏版)》请在冰豆网上搜索。
JUnit使用方法以及测试代码覆盖率
Junit
一、什么是junit
采用测试驱动开发的方式,在开发前先写好测试代码,主要说明被测试的代码会被如何使用,错误处理等,然后开始写代码。
并在测试代码中逐步测试这些代码。
直到最后在测试代码中完全通过。
二、Junit功能
1)管理测试用例。
修改了哪些代码。
这些代码的修改会对哪些部分由影响,通过junit将这次的修改做完成测试。
2)定义了测试代码,textcase根据源代码的测试需要定义每个textcase,并将Textcase添加到相应的Textsuit以方便管理。
3)定义测试环境,在Textcase测试前会先调用“环境”配置。
在测试中使用,当然也可以在测试用例中直接定义测试环境。
4)检测测试结果。
对于每种正常、异常情况下的测试,运行结果是什么。
结果是够是我们预料的等。
都需要有明确的定义。
Junit在这方面提供了强大的功能。
三、Junit核心类
Textsuit:
测试用例的集合
Textcase:
定义运行多个测试用例
TextListener:
测试中若产生事件,会通知TextListener
BaseTextRunner:
TextRunner用来启动测试界面
TextResult:
收集一个测试案例的结果。
测试结果分为失败和错误。
Assert:
当条件成立时,assert方法保持沉默,但若条件不成立就抛出异常
四、使用举例
4.1方法一:
第一步、新建一个Android项目JUnit_Test,file-new-androidproject,然后编写一个Calculator类,newjavaclass,实现简单的加、减、乘、除的计算器,然后对这些功能进行单元测试。
类的代码如下:
packagecom.neusoft;
publicclassCalculator{
privateintresult;
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软件包就被包含进我们这个项目了。
第三步、在Eclipse的PackageExplorer中用右键点击该类弹出菜单,选择new—选择“JunitTextCase”。
在弹出窗口,选择newJUnit4text,在whichmethodstubswouldyouliketocreat?
处选择setUp。
点击“next”后,系统会自动列出你这个类中包含的方法,选择你要进行测试的方法。
此处,我仅对“加、减、乘、除”四个方法进行测试。
点击Finish后,系统会自动生成一个新类CalculatorTest,里面包含一些空的测试用例。
只需要将这些测试用例稍作修改即可使用。
完整的CalculatorTest代码如下:
packagecom.neusoft;
importstaticorg.junit.Assert.*;
importorg.junit.Before;
importorg.junit.Test;
importorg.junit.Ignore;
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(){
fail("Notyetimplemented");
}
@Test
publicvoidtestDivide(){
calculator.add(8);
calculator.divide
(2);
assertEquals(4,calculator.getResult());
}
}
第四步,运行测试代码:
按照上述代码修改完毕后,在CalculatorTest类上点右键,选择“RunAs-JUnitTest”,会弹出下面对话框
选择Useconfigurationspecificsettings,选择AndroidJunitTestLauncher,点击ok。
在结果当中,进度条是红颜色表示发现错误,具体的测试结果在进度条上面有表示“共进行了4个测试,其中1个测试被忽略,一个测试失败”。
点击左侧各个测试类,可在FailureTrace处显示出失败信息。
4.2方法二
这里我们以项目工程EPG为例,进行一下测试。
第一步:
右键点击EPG工程,选择new-Other…-Android下的AndroidTestProject。
如图所示
点击next,进入如下界面。
输入Projectname,这里我输入EPGTest,在Selecttheprojecttotest处选择AnexistingAndroidproject点击Browse选择需要测试的工程。
这里选择的是EPG。
BuildTarget选择与测试工程一致的版本。
此处为Android3.1。
点击finish。
完成创建。
第二部:
在新建的测试程序中添加类,命名为TestWeeklyEPGActivity,让此类继承自ActivityInstrumenttationTestCase2,然后加入所需要的包。
加入的包为所测试工程的Activity的包名加名称。
importcom.sony.btv.epg.jp.basic.Titlebar;
importcom.sony.btv.epg.jp.basic.WeeklyEPGActivity;
importcom.sony.btv.epg.jp.R;
importandroid.test.ActivityInstrumentationTestCase2;
importandroid.view.View;
完整的测试代码如下
packagecom.sony.btv.epg.jp.test;
importcom.sony.btv.epg.jp.basic.Titlebar;
importcom.sony.btv.epg.jp.basic.WeeklyEPGActivity;
importcom.sony.btv.epg.jp.R;
importandroid.test.ActivityInstrumentationTestCase2;
importandroid.view.View;
publicclassTestWeeklyEPGActivityextendsActivityInstrumentationTestCase2{
privateViewmainLayout;
publicTestWeeklyEPGActivity(){
super("com.sony.btv.epg.jp.basic",WeeklyEPGActivity.class);
}
/*(non-Javadoc)
*@seeandroid.test.ActivityInstrumentationTestCase2#setUp()
*/
protectedvoidsetUp()throwsException{
super.setUp();
WeeklyEPGActivitymainActivity=getActivity();
mainLayout=(View)mainActivity.findViewById(R.layout.epg);
}
publicvoidtestCreateTitleBar()
{
assertNotNull(mainLayout);
Titlebartitlebar=null;
titlebar=(Titlebar)mainLayout.findViewById(R.id.epg_titlebar);
assertNotNull(titlebar);
}
}
第三部,进入AndroidManifest.xml,添加
targetPackage="com.sony.btv.epg.jp"android:
name="android.test.InstrumentationTestRunner"/>和name="android.test.runner"/>
第四步,首先运行程序EPG,然后右键点击EPGTest-runas-RunConfigurations,在左侧框内选择AndroidJunitTest目录下的EPGTest,然后点击run运行EPGTest。
第五步,运行结束,可以看到和上面第一种方法一样的结果。
此处不再叠述。
五、案例分析
1.包含必需的包
importstaticorg.junit.Assert.*;
importorg.junit.Before;
importorg.junit.Test;
2.测试类的声明
测试类是一个独立的类,没有任何父类。
测试类的名字也可以任意命名,没有任何局限性。
所以不能通过类的声明来判断它是不是一个测试类。
3.创建一个待测试的对象
要测试哪个类,那么首先就要创建一个该类的对象。
正如上面案例中的代码:
privatestaticCalculatorcalculator=newCalculator();
为了测试Calculator类,必须创建一个calculator对象。
4.测试方法的声明
在测试类中,并不是每一个方法都是用于测试的,必须使用“标注”来明确表明哪些是测试方法。
“标注”是JDK5的一个新特性,用在此处非常恰当。
可以看到,在某些方法的前有@Before、@Test、@Ignore等字样,这些就是标注,以一个“@”作为开头。
这些标注都是JUnit4自定义的,熟练掌握这些标注的含义非常重要。
5.编写一个简单的测试方法
首先,要在方法的前面使用@Test标注,以表明这是一个测试方法。
对于方法的声明也有如下要求:
名字可以随便取,没有任何限制,但是返回值必须为void,而且不能有任何参数。
如果违反这些规定,会在运行时抛出一个异常。
至于方法内该写些什么,那就要看需要测试些什么了。
比如:
@Test
publicvoidtestAdd(){
calculator.add
(2);
calculator.add(3);
assertEquals(5,calculator.getResult());
}
我想测试一下“加法”功能是否正确,就在测试方法中调用几次add函数,初始值为0,先加2,再加3,我们期待的结果应该是5。
如果最终实际结果也是5,则说明add方法是正确的,反之说明它是错的。
assertEquals(5,calculator.getResult());就是来判断期待结果和实际结果是否相等,第一个参数填写期待结果,第二个参数填写实际结果,也就是通过计算得到的结果。
这样写好之后,JUnit会自动进行测试并把测试结果反馈给用户。
JUnit提供了一种方法来区别他们,那就是在这种测试函数的前面加上@Ignore标注,这个标注的含义就是“某些方法尚未完成,暂不参与此次测试”。
这样的话测试结果就会提示你有几个测试被忽略,而不是失败。
一旦你完成了相应函数,只需要把@Ignore标注删去,就可以进行正常的测试。
6.忽略测试某些尚未完成的方法
JUnit提供了一种方法,就是在未完成的测试函数的前面加上@Ignore标注,这个标注的含义就是“某些方法尚未完成,暂不参与此次测试”。
这样的话测试结果就会提示你有几个测试被忽略,而不是失败。
当你完成了相应函数,只需要把@Ignore标注删去,就可以进行正常的测试。
7.Fixture
Fixture的含义就是“在某些阶段必然被调用的代码”。
比如我上面的测试,由于只声明了一个Calculator对象,他的初始值是0,但是测试完加法操作后,他的值就不是0了;接下来测试减法操作,就必然要考虑上次加法操作的结果。
这绝对是一个很糟糕的设计!
我们非常希望每一个测试都是独立的,相互之间没有任何耦合度。
因此,我们就很有必要在执行每一个测试之前,对Calculator对象进行一个“复原”操作,以消除其他测试造成的影响。
因此,“在任何一个测试执行之前必须执行的代码”就是一个Fixture,我们用@Before来标注它,如前面例子所示:
@Before
publicvoidsetUp()throwsException{
calculator.clear();
}
这里不在需要@Test标注,因为这不是一个test,而是一个Fixture。
同理,如果“在任何测试执行之后需要进行的收尾工作”也是一个Fixture,使用@After来标注。
参数timeout,指定被测试方法被允许运行的最长时间应该是多少,如果测试方法运行时间超过了指定的毫秒数,则JUnit认为测试失败。
8.设置最长执行时间
参数timeout,指定被测试方法被允许运行的最长时间应该是多少,如果测试方法运行时间超过了指定的毫秒数,则JUnit认为测试失败。
。
@Test(timeout)
publicvoidtestSubstract(){
calculator.add(10);
calculator.substract
(2);
assertEquals(8,calculator.getResult());
}
9.类级别Fixture的设置方法
注解@BeforeClass修饰用于初始化Fixture的方法。
注解@AfterClass修饰用于注销Fixture的方法
@BeforeClass
publicstaticvoiddbInit(){//类级别Fixture初始化方法
}
@AfterClass
publicstaticvoiddbClose(){//类级别Fixture注销方法
}
类级别的Fixture方法,仅会在测试类中所有测试方法执行之前执行初始化,并在全部测试方法测试完毕之后执行注销方法。
10.JunitGUI
Junit.runner包中定义了Junit测试框架的交互模式。
BaseTextRunner抽象类是这个包的核心,所有Junit框架和外界进行交互的行为都被此包定义。
有三种交互模式:
1)字符串模式
2)Swing模式
3)AWT模式
六、计算通过使用单元测试代码覆盖率
1.安装EclEmma插件
安装EclEmma插件的工程和大部分Eclipse插件相同,在此我选择从站点下载zip文件并解压到eclipse所在的目录中。
进入
2.EclEmma的使用
上面我们已经对Calculator进行了Junit测试,之后我们点击新增按钮选择CoverageasJunitText。
执行之后,程序窗口的代码会变颜色。
其中绿色便是该行代码被完整的执行,红色部分便是该行代码根本没有执行,黄色的行便是该行代码部分被执行。
除此之外,在下面还有一个单独的视图来统计程序的覆盖代码率。
EclEmma提供的Coverage视图能够分层的显示代码的覆盖测试率。
从图中我们可以读出代码运行之后的覆盖率。