您的位置:软件测试 > 开源软件测试 > 开源单元测试工具 > junit
经验总结:JUnit实战
作者:网络转载 发布时间:[ 2013/1/9 14:57:45 ] 推荐标签:

二、JUnit简介及为什么要使用JUint

JUnit是对程序代码进行单元测试的一种Java框架。通过每次修改程序之后测试代码,程序员可以保证代码的的少量变动不会破坏整个系统。要不是有Junit这样的自动化测试工具,代码的的反复测试简直会把人累死而且还可能不准确。现在好了,测试过程可以频繁进行而且还是自动的,所以你可以令程序错误降低到少。它写的是单元测试(Unit Test):软件工程里的白盒测试,是测试某个类的某个方法的功能。XP 中推崇的 test first design 是基于以上的技术。

如果你要写一段代码:

1. 先用 junit 写测试,然后再写代码

2. 写完代码,运行测试,测试失败

3. 修改代码,运行测试,直到测试成功

如果以后对程序进行修改,优化 ( refactoring ),只要再运行测试代码,如果所有的测试都成功,则代码修改完成。

Java 下的 team 开发,一般采用 cvs(版本控制) + ant(项目管理) + junit(集成测试) 的模式:

1. 每天早上上班,每个开发人员从 cvs server 获取一个整个项目的工作拷贝;

2. 拿到自己的任务,先用 junit 写的任务的测试代码;

3. 然后写任务的代码,运行测试,直到测试通过,任务完成;

4. 在下班前一两个小时,各个开发人员把任务提交到 cvs server;

5. 然后由主管对整个项目运行自动测试,哪个测试出错,找相关人员修改,直到所有测试通过。下班...

先写测试,再写代码的好处:

从技术上强制你先考虑一个类的功能,也是这个类提供给外部的接口,而不至于太早陷入它的细节。这是面向对象提倡的一种设计原则。好的测试其实是一个好的文档,这个类使用者往往可以通过查看这个类的测试代码了解它的功能。特别的,如果你拿到别人的一个程序,对他写测试是好的了解这个程序的功能的方法。 xp的原则是 make it simple,不是很推荐另外写文档,因为项目在开发过程中往往处于变动中,如果在早期写文档,以后代码变动后还得同步文档,多了一个工作,而且由于项目时间紧往往文档写的不全或与代码不一致,与其这样,不如不写。而如果在项目结束后再写文档,开发人员往往已经忘记当时写代码时的种种考虑,况且有下一个项目的压力,管理人员也不愿意再为旧的项目写文档,导致以后维护的问题。没有人能保证需求不变动,以往项目往往对需求的变动大为头疼,害怕这个改动会带来其他地方的错误。为此,除了设计好的结构以分割项目外(松耦合),但如果有了测试,并已经建立了一个好的测试框架,对于需求的变动,修改完代码后,只要重新运行测试代码,如果测试通过,也保证了修改的成功,如果测试中出现错误,也会马上发现错在哪里,修改相应的部分,再运行测试,直至测试完全通过。

软件公司里往往存在开发部门和测试部门之间的矛盾:由于开发和测试分为两个部门,多了一层沟通的成本和时间,沟通往往会产生错误的发生。而且极易形成一个怪圈:开发人员为了赶任务,写了烂烂的代码,把它扔给测试人员,然后写其他的任务,测试当然是失败的,又把代码拿回去重写,而且在国内往往一个软件公司技术差的部门是测试部门(好的人都跑去写代码了),测试成了一个很头疼的问题。这种怪圈的根源是责任不清,根据 xp 中的规定:写这个代码的人必须为自己的代码写测试,而且只有测试通过,才算完成这个任务(这里的测试包括所有的测试,如果测试时发现由于你的程序导致别的模块的测试失败,你有责任通知相关人员修改直至集成测试通过),这样可以避免这类问题的发生。

三、安装

1. 获取JUnit的软件包,从Junit(http://www.junit.org/index.htm或http://download.sourceforge.net/junit/)下载新的软件包。这里我使用的是http://download.sourceforge.net/junit/junit2.zip。

2. 将其在适当的目录下解包(我安装在D:junit2)。这样在安装目录(也是你所选择的解包的目录)下你找到一个名为junit.jar的文件。将这个jar文件加入你的CLASSPATH系统变量。(IDE的设置会有所不同,参看你所喜爱的IDE的配置指南)JUnit安装完了。

四、运行

通过前面的介绍,我们对JUnit有了一个大概的轮廓。知道了它是干什么的。现在让我们动手改写上面的测试类testCar使其符合Junit的规范--能在JUnit中运行。

//执行测试的类(JUnit版)

import junit.framework.*;

public class testCar extends TestCase

{

protected int expectedWheels;

protected Car myCar;

public testCar(String name)

{

super(name);

}

protected void setUp()

{

expectedWheels = 4;

myCar = new Car();

}

public static Test suite()

{

/** the type safe way */

/*

TestSuite suite= new TestSuite();

suite.addTest(

new testCar("Car.getWheels")

{

protected void runTest()

{

testGetWheels();

}

}

);

return suite;

*/

/** the dynamic way */

return new TestSuite(testCar.class);

}

public void testGetWheels()

{

assertEquals(expectedWheels, myCar.getWheels());

}

}

改版后的testCar已经面目全非。先让我们了解这些改动都是什么含义,再看如何执行这个测试。

1>import语句,引入JUnit的类。(没问题吧)

2>继承 TestCase 。可以暂时将一个TestCase看作是对某个类进行测试的方法的集合。详细介绍请参看JUnit资料

3>setUp()设定了进行初始化的任务。我们以后会看到setUp会有特别的用处。

4>testGetWheeels()对预期的值和myCar.getWheels()返回的值进行比较,并打印比较的结果。assertEquals是junit.framework.Assert中所定义的方法,junit.framework.TestCase继承了junit.framework.Assert。

5>suite()是一个很特殊的静态方法。JUnit的TestRunner会调用suite方法来确定有多少个测试可以执行。上面的例子显示了两种方法:静态的方法是构造一个内部类,并利用构造函数给该测试命名(test name, 如 Car.getWheels),其覆盖的runTest()方法,指明了该测试需要执行那些方法--testGetWheels()。动态的方法是利用内省(reflection)来实现runTest(),找出需要执行那些测试。此时测试的名字即是测试方法(test method,如testGetWheels)的名字。JUnit会自动找出并调用该类的测试方法。

6>将TestSuite看作是包裹测试的一个容器。如果将测试比作叶子节点的话,TestSuite是分支节点。实际上TestCase,TestSuite以及TestSuite组成了一个composite Pattern。JUnit的文档中有一篇专门讲解如何使用Pattern构造Junit框架。有兴趣的朋友可以查看JUnit资料。

上一页1234下一页
软件测试工具 | 联系我们 | 投诉建议 | 诚聘英才 | 申请使用列表 | 网站地图
沪ICP备07036474 2003-2017 版权所有 上海泽众软件科技有限公司 Shanghai ZeZhong Software Co.,Ltd