软件测试实验单元测试工具JUNIT.docx

上传人:b****6 文档编号:6393806 上传时间:2023-01-06 格式:DOCX 页数:20 大小:440.97KB
下载 相关 举报
软件测试实验单元测试工具JUNIT.docx_第1页
第1页 / 共20页
软件测试实验单元测试工具JUNIT.docx_第2页
第2页 / 共20页
软件测试实验单元测试工具JUNIT.docx_第3页
第3页 / 共20页
软件测试实验单元测试工具JUNIT.docx_第4页
第4页 / 共20页
软件测试实验单元测试工具JUNIT.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

软件测试实验单元测试工具JUNIT.docx

《软件测试实验单元测试工具JUNIT.docx》由会员分享,可在线阅读,更多相关《软件测试实验单元测试工具JUNIT.docx(20页珍藏版)》请在冰豆网上搜索。

软件测试实验单元测试工具JUNIT.docx

软件测试实验单元测试工具JUNIT

武汉轻工大学

 

软件测试实验报告

实验一单元测试工具JUNIT

 

姓名:

李娅娅

学号:

1505110015

班级:

软工1503

指导老师:

丁月华

1.实验目的

了解自动化测试工具JUnit的架构、功能,学习如何下载、安装JUnit,掌握使用JUnit对Java程序进行单元测试的方法。

2.实验步骤

2.1导入jar包

右击项目名,单击BuildPath中的AddLibraries..

选择UserLibariry。

新建一个存放Junit的包的库

将junit-4.7.jar导入

Jar包导入完成。

2.2编写第一个Junit测试类

2.2.1Calculator类

编写被测试类Calculator:

(拷贝)

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;

}

}

2.2.2CalculatorTest类

编写CalculatorTest类,用于测试Calculator类:

(拷贝)

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());

}

}

2.2.3运行测试

在类名上右击,选择RunAs→JunitTest

得到Junit面板,并显示了哪些测试是成功的,哪些是失败的以及哪些是未执行(直接跳过了):

2.3使用JUnit对Money类进行单元测试

2.3.1Money类

(拷贝)

publicclassMoney{

privateintfAmount;//货币余额

privateStringfCurrency;//货币类型

publicMoney(intamount,Stringcurrency){

fAmount=amount;

fCurrency=currency;

}

publicintamount(){

returnfAmount;

}

publicStringcurrency(){

returnfCurrency;

}

publicMoneyadd(Moneym){

//add方法把两个Money对象相加,合成一个Money对象

returnnewMoney(amount()+m.amount(),currency());

}

publicbooleanequals(ObjectanObject){

//equals方法判断两个Money对象是否相等

if(anObjectinstanceofMoney){

MoneyaMoney=(Money)anObject;

returnaMoney.currency().equals(currency())&&amount()==aMoney.amount();

}

returnfalse;

}

}

现在要对Money类的add方法进行测试,步骤如下:

2.3.2MoneyTest类

(1)创建对象

定义几个Money类的对象

Moneyresult;

Moneym12CHF=newMoney(12,"CHF");

Moneym14CHF=newMoney(14,"CHF");

Moneyexpected=newMoney(26,"CHF");//预期的运行结果

(2)addTest()

在MoneyTest类中编写testAdd方法,对Money类中的add()方法进行测试:

@Test

publicvoidtestAdd(){

result=m12CHF.add(m14CHF);

assertTrue(expected.equals(result));//判断运行结果是否与预期值相同

}

(3)testEquals()

@Test

publicvoidtestEquals()

{

assertTrue(!

m12CHF.equals(null));

assertTrue(!

m12CHF.equals(m14CHF));

assertEquals(m12CHF,m12CHF);

assertEquals(m12CHF,newMoney(12,"CHF"));

}

2.3.3运行测试

测试通过

2.4Fixture和几个标签

Fixture的含义就是“在某些阶段必然被调用的代码”。

比如我们上面的测试,由于只声明了一个Calculator对象,他的初始值是0,但是测试完加法操作后,他的值就不是0了;接下来测试减法操作,就必然要考虑上次加法操作的结果。

这绝对是一个很糟糕的设计!

我们非常希望每一个测试都是独立的,相互之间没有任何耦合度。

因此,我们就很有必要在执行每一个测试之前,对Calculator对象进行一个“复原”操作,以消除其他测试造成的影响。

因此,“在任何一个测试执行之前必须执行的代码”就是一个Fixture,我们用@Before来标注它,如前面例子中的setUp()方法所示:

这里不在需要@Test标注,因为这不是一个test,而是一个Fixture。

同理,如果“在任何测试执行之后需要进行的收尾工作”也是一个Fixture,使用@After来标注。

2.4.1代码测试

publicclassTTest{

@BeforeClass

publicstaticvoidbeforeClass(){

System.out.println("beforeClass");

}

@AfterClass

publicstaticvoidafterClass(){

System.out.println("afterClass");

}

@Before

publicvoidbefore(){

System.out.println("before");

}

@Test

publicvoidtestAdd(){

intz=newT().add(5,3);

assertThat(z,is(8));

assertThat(z,allOf(greaterThan(5),lessThan(10)));

}

@Test(expected=java.lang.ArithmeticException.class,timeout=100)

publicvoidtDivide(){

intz=newT().divide(8,0);

}

@After

publicvoidafter(){

System.out.println("after");

}

}

2.4.2运行结果

在控制台中得到运行结果:

在Junit选型卡中得到:

(1)结果分析

在Junit选项卡中由于代码找不到T类,而使方法运行错误。

在控制台中输出两次before和两次after,是因为在类中test了两个方法,每运行一个方法,@before和@after下的方法就是默认执行。

2.4.3标签学习

(1)@Test

测试方法

(2)@Before

使用了该元数据的方法在每个测试方法执行之前都要执行一次,一般做初始化方法。

(3)@After

使用了该元数据的方法在每个测试方法执行之后要执行一次,一般用于释放资源。

(4)@ignore

该元数据标记的测试方法在测试中会被忽略。

你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方法。

比如:

@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。

(5)@BeforeClass

所有测试开始之前运行,一个测试类只能有一个,并且必须声明为publicstatic。

该方法在内存中只存在一份实例,比较适合加载配置文件。

(6)@AfterClass:

所有测试结束之后运行 ,一个测试类只能有一个,并且必须声明为publicstatic。

 通常用来对资源进行清理,比如关闭数据库的连接。

(备注:

为什么需要@BeforeClass和@AfterClass,我们来看看他们是否适合完成如下功能:

有一个类是负责对大文件(超过500兆)进行读写,他的每一个方法都是对文件进行操作。

换句话说,在调用每一个方法之前,我们都要打开一个大文件并读入文件内容,这绝对是一个非常耗费时间的操作。

如果我们使用@Before和@After,那么每次测试都要读取一次文件,效率及其低下。

这里我们所希望的是在所有测试一开始读一次文件,所有测试结束之后释放文件,而不是每次测试都读文件。

JUnit的作者显然也考虑到了这个问题,它给出了@BeforeClass和@AfterClass两个Fixture来帮我们实现这个功能。

从名字上就可以看出,用这两个Fixture标注的函数,只在测试用例初始化时执行@BeforeClass方法,当所有测试执行完毕之后,执行@AfterClass进行收尾工作。

JUnit4的单元测试用例执行顺序为:

@BeforeClass->@Before->@Test->@After->@AfterClass。

每一个测试方法的调用顺序为:

@Before->@Test->@After。

可以根据以上给定的标记来构造测试类中的测试方法,一般说来遵守以下约定:

类放在test包中

类名用XXXTest结尾

方法用testMethod命名

2.5限时测试

@Test(timeout=value),例如@Test(timeout=1000)

2.5.1被测源代码

2.5.2测试代码

@Test(timeout=1000)

publicvoidtestSquareRoot(){

calculator.squareRoot(4);

assertEquals(2,calculator.getResult());

}

2.5.3运行测试

在测试代码中Timeout参数表明了设定的时间,单位为毫秒,因此1000就代表1秒,测试的方法超过了设定的时间表示失败。

2.6异常测试

对除法运算中的“除0异常”进行测试

2.7综合练习

2.7.1测试代码

publicclassCalculatorTest{

privatestaticCalculatorcalculator=newCalculator();

@BeforeClass

publicstaticvoidbeforeClass(){

System.out.println("beforeClass");

}

@AfterClass

publicstaticvoidafterClass(){

System.out.println("afterClass");

}

@Before

publicvoidbefore(){

System.out.println("before");

}

@After

publicvoidafter(){

System.out.println("after");

}

@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());

}

@Test(timeout=1000)

publicvoidtestSquareRoot(){

calculator.squareRoot(4);

assertEquals(2,calculator.getResult());

}

@Test(expected=ArithmeticException.class)

publicvoiddivideByZero(){

calculator.divide(0);

}

}

2.7.2运行测试

(1)控制台

分析:

在代码中定义了@BeforeClass和@AfterClass标签,因此,在输出的首尾有这标签下定义的输出信息。

代码中编写了6个测试方法,因此对@Before,@After标签下的输出信息打印了5遍(其中方法testMultiply使用了@Ignore标签)。

(2)Junit选项卡

测试结果为三个通过,一个忽略,一个失败,一个错误。

2.8运行器@RunWith

当把测试代码提交给JUnit框架后,框架就会通过Runner来运行代码。

在JUnit中有很多个Runner,他们负责调用测试代码,每一个Runner都有各自的特殊功能,你要根据需要选择不同的Runner来运行你的测试代码。

JUnit中有一个默认Runner,如果你没有指定,那么系统自动使用默认Runner来运行你的代码。

也就是说,下面两段代码含义是完全一样的:

publicclassCalculatorTest{...}//该方式就是使用了默认的Runner

等价于

@RunWith(JUnit4ClassRunner.class)

publicclassCalculatorTest{...}//声明了Runner

从上述例子可以看出,要想指定一个Runner,需要使用@RunWith标注,并且把你所指定的Runner作为参数传递给它。

另外一个要注意的是,@RunWith是用来修饰类的,而不是用来修饰函数的。

只要对一个类指定了Runner,那么这个类中的所有函数都被这个Runner来调用。

是对其他Runner的学习:

2.8.1参数化测试@RunWith(Parameterized.class)

把一组组的测试数据集中放在一个集合中,这个集合作为测试类的参数,进行集中测试,避免为每一组测试数据写一个测试方法。

你可能遇到过这样的函数,它的参数有许多特殊值,或者说他的参数分为很多个区域。

比如,一个对考试分数进行评价的函数,返回值分别为“优秀,良好,一般,及格,不及格”,因此你在编写测试的时候,至少要写5个测试,把这5中情况都包含了,这确实是一件很麻烦的事情。

我们还使用我们先前的例子,测试一下“计算一个数的平方”这个函数,暂且分三类:

正数、0、负数。

(1)测试代码

按照之前的方法,要测试三类就需要编写三个测试方法:

publicclassAdvancedTest{

privatestaticCalculatorcalculator=newCalculator();

@Before

publicvoidclearCalculator(){

calculator.clear();

}

@Test

publicvoidsquare1(){

calculator.square

(2);

assertEquals(4,calculator.getResult());

}

@Test

publicvoidsquare2(){

calculator.square(0);

assertEquals(0,calculator.getResult());

}

@Test

publicvoidsquare3(){

calculator.square(-3);

assertEquals(9,calculator.getResult());

}

}

运行结果:

为了简化类似的测试,JUnit4提出了“参数化测试”的概念,只写一个测试函数,把这若干种情况作为参数传递进去,一次性的完成测试。

代码如下:

@RunWith(Parameterized.class)//更改默认的测试运行器为Parameterized.class

publicclassSquareTest{

privatestaticCalculatorcalculator=newCalculator();

privateintparam;//声明变量存放输入参数(用来计算实际结果)

privateintresult;//声明变量存放预期值

//声明一个返回值为Collection的公共静态方法,并用@Parameters修饰

@Parameters

publicstaticCollectiondata(){

returnArrays.asList(newObject[][]{{2,4},{0,0},{-3,9}});

}

//为测试类声明一个带有参数的公共构造方法,并为声明变量赋值

publicSquareTest(intparam,intresult){

this.param=param;

this.result=result;

}

@Test

publicvoidsquare(){

calculator.square(param);

assertEquals(result,calculator.getResult());

}

}

分析:

首先,要为这种测试专门生成一个新的类,而不能与其他测试共用同一个类,此例中我们定义了一个SquareTest类。

然后,你要为这个类指定一个Runner,而不能使用默认的Runner了,因为特殊的功能要用特殊的Runner。

@RunWith(Parameterized.class)这条语句就是为这个类指定了一个ParameterizedRunner。

第二步,定义一个待测试的类,并且定义两个变量,一个用于存放参数,一个用于存放期待的结果。

接下来,定义测试数据的集合,也就是上述的data()方法,该方法可以任意命名,但是必须使用@Parameters标注进行修饰。

之后是构造函数,其功能就是对先前定义的两个参数进行初始化。

(2)测试结果

2.8.2测试套件@RunWith(Suite.class)

通过前面的案例学习到,在一个项目中,只写一个测试类是不可能的,我们会写出很多很多个测试类。

可是这些测试类必须一个一个的执行,也是比较麻烦的事情。

鉴于此,JUnit为我们提供了打包测试的功能,将所有需要运行的测试类集中起来,一次性的运行完毕,大大的方便了我们的测试工作。

具体测试套件代码如下:

(1)测试代码

@RunWith(Suite.class)

@Suite.SuiteClasses({CalculatorTest.class,SquareTest.class})

//测试套件的入口类,该类不包含任何方法,

//更改测试运行器Suite.class,将测试类作为数组传入到Suite.SuiteClasses({});

publicclassSuiteTest{

}

这个测试代码表示将CalculatorTest.class和SquareTest.class同时进行测试。

运行测试,可以看到两个测试类的测试结果:

(2)测试结果

3.实验总结

JUnit通过单元测试,能在开发阶段就找出许多Bug,并且,多个TestCase可以组合成TestSuite,让整个测试自动完成,尤

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1