使⽤Netbeans⾥的JUnit进⾏软件单元测试
软件测试是软件开发阶段中的⼀个重要环节,良好的测试⽅法是保证软件质量的根基。软件测试根据软件开发阶段按过程划分为:1.单元测试 2.集成测试 3.确认测试 4.验收测试 5.系统测试。
什么是单元测试呢?
单元测试是指将测试集成到创建的所有代码中,并且在每次执⾏构建时运⾏这些测试的过程。在这个过程中,不仅可以进⾏语法错的检查⽽且可以⽅便的进⾏语义错误的检查。现在有⼀些常⽤的单元测试框架:
1.JUnit
2.TestNG
3.Artima SuiteRunner
其中,JUnit在单元测试中占有的⽐例较⼤。JUnit是⼀个开源的测试框架,通过这个框架可以快速的实现测试⽤例。⼀个JUnit测试⽤例就是⼀个从TestCase派⽣的独⽴的类,在类中通常包括⼀些测试⽅法。JUnit中提供了很多断⾔⽅法⽤来测试不同的条件,
assertEquals(a, b)
测试a是否等于b(a和b是原始类型数值(primitive value) 或者必须为实现⽐较⽽具有equal⽅法)
assertFalse(a)
测试a是否为false (假),a是⼀个Boolean数值。
assertTrue(a)
测试a是否为true (真),a是⼀个Boolean 数值
assertNotNull(a)
测试a是否⾮空,a是⼀个对象或者null 。
assertNull(a)
测试a是否为null,a是⼀个对象或者null 。
assertNotSame(a, b)
测试a和b是否没有都引⽤同⼀个对象。
assertSame(a, b)
测试a和b是否都引⽤同⼀个对象。
下⾯就⽤⼀个简单的例⼦来说明如何使⽤Netbeans⾥的JUnit来进⾏测试。
1.创建⼀个Java应⽤程序项⽬,取名叫JUnitTest
2.创建⼀个Java类,取名叫"Account",代码如下,⾥⾯的get和set⽅法就是要被测试的⽅法。
public class Account {
private int ID;
private String name;
public String getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.在项⽬窗⼝中,按照如下图⽅式操作:
4.这时会弹出⼀个“创建测试”的窗体,如图:
解释其中个别选项:“测数初始化函数”会⾃动创建setUp⽅法,⽤于初始化字段、启⽤⽇志记录以及重置环境变量等任务的⽅法,“测试释放⽅法”⾃动创建tearDown⽅法,⽤于在测试运⾏完后进⾏清理⼯作,“默认⽅法主体"⾃动创建测试⽅法中的代码,可以根据这些代码模板进⾏修改。
5.修改AccountTest类中的代码,如下,
package junittest;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
public class AccountTest {
public AccountTest() {
}
@Before
public void setUp() {
System.out.println("测试开始");
}
@After
public void tearDown() {
System.out.println("测试结束");
}
@Test
public void testID() {
System.out.println("getID");
Account instance = new Account();
instance.setID(100);
int result = ID();
assertEquals(100, result); //查看ID值是否为100
}
@Test
public void testName() {
System.out.println("getName");
Account instance = new Account();
instance.setName("Lu Yao");
String result = Name();
assertEquals("Zhang Fan", result); //查看Name值是否为Zhang Fan
}
}
6.在项⽬节点上单击右键,选择“测试”,可以看到如下输出:
testID测试会通过,因为测试的值和设置的值相同
testName测试不会通过,因为测试的值和设置的值不同
这就是测试的过程。下⼀讲会举⼀个复杂⼀点的例⼦。
上⼀篇主要以⼀个⼩例⼦来解释了如何在Netbeans下使⽤JUnit。可能⼤家只是粗略的会使⽤JUnit,只有了⼀个简单的初级感受。我想在这篇⽇志⾥,将JUnit的知识梳理⼀下,然后再以⼀个⼩例⼦来做以下测试的演⽰。
⼀、⼀些概念性问题:
⽩盒测试——把测试对象看作⼀个打开的盒⼦,程序内部的逻辑结构和其他信息对测试⼈员是公开的。
⿊盒测试——已知产品的功能设计规格,不考虑程序内部结构,进⾏测试证明每个实现了的功能是否符合要求
灰盒测试——介于⽩盒和⿊盒测试之间,即关注输出对输⼊的正确性,也关注程序内部表现。
回归测试——软件或环境的修复或更正后的“再测试”,⾃动测试⼯具对这类测试尤其有⽤。
⼆、单元测试的好处 :
A、提⾼开发速度——测试是以⾃动化⽅式执⾏的,提升了测试代码的执⾏效率。
B、提⾼软件代码质量——它使⽤⼩版本发布⾄集成,便于实现⼈员排错。同时引⼊重构概念,让代码更⼲净和富有弹性。
C、提升系统的可信赖度——它是回归测试的⼀种。⽀持修复或更正后的“再测试”,可确保代码的正确性。
三、单元测试的针对对象 :
A、⾯向过程的软件开发针对过程。
B、⾯向对象的软件开发针对对象。
C、可以做类测试,功能测试,接⼝测试(最常⽤于测试类中的⽅法)。
四、下⾯是JUnit⼀些特性的总结:
1) 提供的API可以让你写出测试结果明确的可重⽤单元测试⽤例
2) 提供了三种⽅式来显⽰你的测试结果,⽽且还可以扩展
3) 提供了单元测试⽤例成批运⾏的功能
4) 超轻量级⽽且使⽤简单,没有商业性的欺骗和⽆⽤的向导
5) 整个框架设计良好,易扩展,对不同性质的被测对象,如Class,Jsp,Servlet,Ejb等,Junit有不同的使⽤技巧。
6) 使⽤断⾔⽅法判断期望值和实际值差异,返回Boolean值。
7) 测试驱动设备使⽤共同的初始化变量或者实例。
8) 测试包结构便于组织和集成运⾏。
9) ⽀持图型交互模式和⽂本交互模式。
五、JUnit的好处和JUnit单元测试编写原则:
好处: A、可以使测试代码与产品代码分开。
B、针对某⼀个类的测试代码通过较少的改动便可以应⽤于另⼀个类的测试。
C、易于集成到测试⼈员的构建过程中,JUnit和Ant的结合可以实施增量开发。
D、JUnit是公开源代码的,可以进⾏⼆次开发。
E、可以⽅便地对JUnit进⾏扩展。
编写原则:
A、是简化测试的编写,这种简化包括测试框架的学习和实际测试单元的编写。
B、是使测试单元保持持久性。
C、是可以利⽤既有的测试来编写相关的测试。
六、JUnit框架组成 :
A、对测试⽬标进⾏测试的⽅法与过程集合,可称为测试⽤例(TestCase)。
B、测试⽤例的集合,可容纳多个测试⽤例(TestCase),将其称作测试包(TestSuite)。
C、测试结果的描述与记录。(TestResult) 。
D、测试过程中的事件监听者(TestListener)。
E、每⼀个测试⽅法所发⽣的与预期不⼀致状况的描述,称其测试失败元素(TestFailure) 。
F、JUnit Framework中的出错异常(AssertionFailedError)。
JUnit框架是⼀个典型的Composite模式:TestSuite可以容纳任何派⽣⾃Test的对象;当调⽤TestSuite对象的run()⽅法是,会遍历⾃⼰容纳的对象,逐个调⽤它们的run()⽅法。
七、JUnit中常⽤的接⼝和类 :
1)Test接⼝——运⾏测试和收集测试结果
Test接⼝使⽤了Composite设计模式,是单独测试⽤例 (TestCase),聚合测试模式(TestSuite)及测试扩展(TestDecorator)的共同接⼝。 它的public int countTestCases()⽅法,它来统计这次测试有多少个TestCase,另外⼀个⽅法就是public void run( TestResult ),TestResult是实例接受测试结果, run⽅法
2)TestCase抽象类——定义测试中固定⽅法
TestCase是Test接⼝的抽象实现,(不能被实例化,只能被继承)其构造函数TestCase(string name)根据输⼊的测试名称name创建⼀个测试实例。由于每⼀个TestCase在创建时都要有⼀个名称,若某测试失败了,便可识别出是哪个测试失败。
TestCase类中包含的setUp()、tearDown()⽅法。setUp()⽅法集中初始化测试所需的所有变量和实例,并且在依次调⽤测试类中的每个测试⽅法之前再次执⾏setUp()⽅法。tearDown()⽅法则是在每个测试⽅法之后,释放测试程序⽅法中引⽤的变量和实例。
开发⼈员编写测试⽤例时,只需继承TestCase,来完成run⽅法即可,然后JUnit获得测试⽤例,执⾏它的run⽅法,把测试结果记录在TestResult之中。
3)Assert静态类——⼀系列断⾔⽅法的集合
Assert包含了⼀组静态的测试⽅法,⽤于期望值和实际值⽐对是否正确,即测试失败,Assert类就会抛出⼀个AssertionFailedError异常,JUnit测试框架将这种错误归⼊Failes并加以记录,同时标志为未通过测试。如果该类⽅法中指定⼀个String类型的传参则该参数将被做为AssertionFailedError异常的标识信息,告诉测试⼈员改异常的详细信息。
JUnit 提供了6⼤类31组断⾔⽅法,包括基础断⾔、数字断⾔、字符断⾔、布尔断⾔、对象断⾔。
其中assertEquals(Object expcted,Object actual)内部逻辑判断使⽤equals()⽅法,这表明断⾔两个实例的内部哈希值是否相等时,最好使⽤该⽅法对相应类实例的值进⾏⽐较。⽽assertSame(Object expected,Object actual)内部逻辑判断使⽤了Java运算符“==”,这表明该断⾔判断两个实例是否来⾃抽象类的使用
于同⼀个引⽤(Reference),最好使⽤该⽅法对不同类的实例的值进⾏⽐对。asserEquals(String message,String expected,String actual)该⽅法对两个字符串进⾏逻辑⽐对,如果不匹配则显⽰着两个字符串有差异的地⽅。ComparisonFailure类提供两个字符串的⽐对,不匹配则给出详细的差异字符。
4)TestSuite测试包类——多个测试的组合
TestSuite类负责组装多个Test Cases。待测得类中可能包括了对被测类的多个测试,⽽TestSuit负责收集这些测试,使我们可以在⼀个测试中,完成全部的对被测类的多个测试。
TestSuite类实现了Test接⼝,且可以包含其它的TestSuites。它可以处理加⼊Test时的所有抛出的异常。
TestSuite处理测试⽤例有6个规约(否则会被拒绝执⾏测试)
A 测试⽤例必须是公有类(Public)
B 测试⽤例必须继承与TestCase类
C 测试⽤例的测试⽅法必须是公有的( Public )
D 测试⽤例的测试⽅法必须被声明为Void
E 测试⽤例中测试⽅法的前置名词必须是test
F 测试⽤例中测试⽅法误任何传递参数
5)TestResult结果类和其它类与接⼝
TestResult结果类集合了任意测试累加结果,通过TestResult实例传递个每个测试的Run()⽅法。TestResult在执⾏TestCase是如果失败会异常抛出
TestListener接⼝是个事件监听规约,可供TestRunner类使⽤。它通知listener的对象相关事件,⽅法包括测试开始startTest(Test test),测试结束endTest(Test test),错误,增加异常addError(Test test,Throwable t)和增加失败addFailure(Test test,AssertionFailedError t)
TestFailure失败类是个“失败”状况的收集类,解释每次测试执⾏过程中出现的异常情况。其toString()⽅法返回“失败”状况的简要描述。
下⾯是⼀个测试例⼦,测试⼀个实现加减乘除的类。先⽤Netbeans⽣成⼀个项⽬,取名叫Calc,然后在建⽴⼀个类Calc.java。
实现加减乘除的类是:Calc.java,代码如下:
package calc;
public class Calc {
public int add(int a,int b){
return a + b;
}
public int minus(int a,int b){
return a - b;
}
public int multiply(int a, int b ){
return a * b;
}
public int divide(int a , int b )throws Exception
{
if(0 == b){
throw new Exception("除数不能为零");
}
}
}
按照上⼀节介绍的办法去⾃动⽣成测试类:CalcTest.java,然后修改测试类如下所⽰:package calc;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
public class CalcTest {
public CalcTest() {
}
private Calc ca;
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
ca = new Calc();
}
@After
public void tearDown() {
}
@Test
public void testAdd() {
System.out.println("add");
int a = 2;
int b = 3;
Calc instance = new Calc();
int expResult = 5;
int result = instance.add(a, b);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail. // fail("The test case is a prototype.");
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论