5.4 JUnit测试
在Eclipse中可以很方便地使用JUnit创建用于对某一应用程序进行测试的测试用例和测试套件,并能运行它们以完成测试。
5.4.1 JUnit测试用例
下面通过一个简单的例子来说明如何进行JUnit单元测试。
(1)首先新建一个名为“Chapter05”的项目(前面章节已有在Eclipse中创建项目的介绍,这里不再赘述)。
(2)要创建测试用例,还必须将junit.jar文件导入到项目的构建路径中,具体步骤如下:
1在项目Chapter05上右击,在弹出的下拉菜单中选择【属性】命令,打开项目Chapter05的属性对话框,如图5-4所示。
图5-4 打开项目属性对话框
2单击【属性】命令,将弹出如图5-5所示的窗口。
图5-5 Java构建路径对话框
在该窗口中选择“Java构建路径”,单击右边的“库”选项卡。
3 在库选项卡中单击【添加变量…】按钮,将弹出如图5-6所示的对话框,在该对话框中选择JUNIT_HOME变量,添加junit.jar文件。单击【确定】按钮,添加构建路径成功。
图5-6 添加变量到构建路径
注意
JUNIT_HOME变量也就是在5.3节中JUnit的JUNIT_HOME设置路径(确切地说是junit.jar的路径)。
设置好Java构建路径后,就可以创建测试用例了。
在创建测试用例之前,为项目Chapter05创建一个类Person。该类存放于“cn.com.twm”包下。关于包和类的创建,前面都讲过,这里不再赘述。
接下来在Java编辑器中为Person类添加如下一段代码。
Person.java的代码:
package cn.com.twm; public class Person { private String name; private String sex; private int high; private int age; public Person (String name,String sex,int high,int age){ this.name=name; this.sex=sex; this.high=high; this.age=age; } public int getAge() {return age;} public boolean setAge(int age) { if(age>25) return false; this.age = age; return true; } public int getHigh() {return high;} public void setHigh(int high) {this.high = high;} public String getName() {return name;} public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
该程序主要为人创建了一个Person类,同时定义了4个属性,即name(姓名)、sex(性别)、high(身高)、age(年龄)。
注意
(1)在实际项目中,不建议使用默认包。
(2)给包起名的时候,最好符合实际,通俗易懂。“cn.com.twm”为一个网站网址的倒序写法。
创建测试用例的具体步骤如下:
1右击包资源管理器中的Chapter05项目下的cn.com.twm包,在弹出的下拉菜单中选择【新建→其他…】命令,打开新建窗口,如图5-7所示。
图5-7 新建JUnit测试用例
2展开【Java→JUnit】节点,然后选中“JUnit测试用例”,单击【下一步】按钮,将打开新建JUnit测试用例窗口,如图5-8所示。
图5-8 设置新建JUnit测试用例
3在“包”字段中输入包的名称“cn.com.twm”。在“名称”字段中输入测试用例名“PersonTest”。在“想要创建哪些方法存根”字段中选中“setUP”和“tearDown”两个复选框,这两个方法用来建立和清理测试用例中的数据和对象。最后在“正在测试的类”字段中输入要测试的类名“cn.com.twm.Person”,单击【下一步】按钮,将弹出选择测试方法存根对话框,如图5-9所示。
图5-9 选择测试方法存根
4在需要测试的方法的复选框中打上钩,这里选择getHigh()、getName()、setAge()3个方法。这样JUnit向导就能够为它们创建存根(stub)。选择完后,单击【完成】按钮,PersonTest测试类创建完成。
同时,在Java编辑器中给出了PersonTest类的初始代码,如图5-10所示。
图5-10 生成的初始代码
PersonTest类的初始代码如下所示:
package cn.com.twm; import junit.framework.TestCase; public class PersonTest extends TestCase { protected void setUp() throws Exception {super.setUp();} protected void tearDown() throws Exception {super.tearDown();} public void testSetAge() {fail("尚未实现");} public void testGetHigh() {fail("尚未实现");} public void testGetName() {fail("尚未实现");} }
代码说明:
(1)由于PersonTest类是在cn.com.twm包下定义的,所以要用到关键字package导入该包。
(2)PersonTest类默认继承了TestCase类,TestCase类是一个抽象类,其中定义了setUp()和tearDown()两个方法,这样在PersonTest类中需要实现这两个方法。
(3)接下来,为想要测试的对象编写测试方法。由于系统有选择测试方法存根的功能,会自动实现待测试方法的空实现。系统默认的方法名为在待测试的原方法前面加上一个test。
下面开始在PersonTest类中添加测试代码,以完成测试功能。
在3个test方法中分别执行setAge()、getHigh()和getName()方法,这样就能对结果使用JUnit断言方法。因此需要一个Person类中的对象来调用这些方法,可以在setUp()方法中初始化它,一旦初始化成功,就可以在测试方法中调用。
对PersonTest.java中的setUp()方法做如下修改:
public class PersonTest extends TestCase { Person testPerson;//加载Person对象 protected void setUp() throws Exception { super.setUp(); testPerson=new Person("twm","boy",175,24);//初始化Person对象 }
初始化完成后,接下来再修改3个test方法,为它们创建JUnit断言方法(基本的断言方法在表5-1中有讲述)。
修改后的代码为:
public void testGetHigh() { assertNotNull(testPerson.getHigh());//添加assertNotNull()断言方法 } public void testSetAge() { assertTrue(testPerson.setAge(27));//添加assertTrue()断言方法 } public void testGetName() { assertEquals(testPerson.getName(),"tem");//添加assertEquals()断言方法 }
添加完毕后,保存PersonTest类。
在Eclipse平台的工具栏中单击运行按钮 旁的倒三角形,在弹出的菜单中选择【运行方式→JUnit测试】。测试类开始运行,同时在JUnit视图中显示测试结果,如图5-11所示。
图5-11 测试结果
从JUnit视图中可以明显地看到,有错误出现。在JUnit视图中,有一个测试通过,另外两个都打上了叉,同时下面也给出了故障跟踪提示。
单击3个test方法中出错的第一个方法testSetAge,下面“故障跟踪”中将显示对应的错误项,发现是断言失败错误(junit.framework.AssertionFailedError)。再双击下面的错误跟踪,Java编辑器中的光标会自动跳转到出错的代码处:
public void testSetAge() { assertTrue(testPerson.setAge(27));//出错的地方 }
断言方法assertTrue()的目的是判断它的参数是否为true。在Person.java中,定义了age必须小于25才为true,在该处的age值为27,已经大于25了,所以返回的是false。由此推断断言方法assertTrue()不通过,测试失败。将27改为比25小的值(例如23),再次测试,结果故障排除,测试成功,在JUnit视图上的测试方法testSetAge已经打上钩了,如图5-12所示。
图5-12 修改后的再次测试结果
用同样的方式继续查找testGetName方法的错误,错误的代码为:
public void testGetName() { assertEquals(testPerson.getName(),"tem");//出错的地方 }
断言方法assertEquals()的目的是判断参数中的两个值是否相等。结果发现“tem”和Person初始化的值“twm”不相等,所以产生了测试失败。修改值“tem”为“twm”,保存再次测试,果然是这里的错误,测试成功。
这时JUnit视图中顶部的菜单栏变成了绿色,“故障跟踪”栏中的错误跟踪也消失了,表明测试全部通过,如图5-13所示。
图5-13 测试全部通过
5.4.2 JUnit测试套件
在Eclipse中还提供了一个JUnit测试套件以方便多个类进行测试的情况。
Eclipse中提供了JUnit测试套件向导,利用该向导可以更加方便地创建JUnit测试套件。在创建测试套件之前,先创建一个测试用例,取名为PersonTest2.java。此测试用例主要用来测试Person类中的testGetHigh()方法。具体添加代码如下所示:
package cn.com.twm; import junit.framework.TestCase; public class PersonTest2 extends TestCase { Person testPerson; protected void setUp() throws Exception { super.setUp(); testPerson=new Person("twm","boy",175,23); } protected void tearDown() throws Exception { super.tearDown(); } public void testGetHigh() { assertNotNull(testPerson.getHigh());//assertNotNull()方法判断是否非空 } }
下面为项目Chapter05创建JUnit测试套件,具体的步骤如下:
1右击包资源管理器中的Chapter05项目下的cn.com.twm包,在弹出的下拉菜单中选择【新建→其他…】命令,打开新建窗口,如图5-14所示。
图5-14 创建测试套件
2展开【Java→JUnit】节点,然后选中“JUnit测试套件”,单击【下一步】按钮,将打开新建JUnit测试套件窗口,如图5-15所示。
图5-15 设置测试类
3在“包”字段中输入包名cn.com.twm,窗口会出现选择“要包括在套件中的测试类”,将“PersonTest”和“PersonTest2”前面的复选框都选上,最后单击【完成】按钮。
注意
在第②步中,单击【下一步】按钮时,系统就为该测试套件自动取了一个名称,为AllTests。
单击【完成】按钮后,向导将自动生成AllTest类的代码,如下所示:
package cn.com.twm; import junit.framework.Test; import junit.framework.TestSuite; public class AllTests { public static Test suite() { TestSuite suite = new TestSuite("Test for cn.com.twm"); //$JUnit-BEGIN$ suite.addTestSuite(PersonTest.class); suite.addTestSuite(PersonTest2.class); //$JUnit-END$ return suite; } }
保存AllTests.java,在Eclipse平台的工具栏中单击运行按钮 旁的倒三角形,在弹出的菜单中选择【运行方式→JUnit测试】,结果如图5-16所示。
图5-16 测试套件的测试结果
由此可见,PersonTest.java和PersonTest2.java两个测试用例都测试成功,从而推断AllTest.java测试套件类测试也一定成功。
其实,测试套件就像一个批处理一样,是一个总的测试,包含了许多个测试用例。