java单元测试是什么,什么是单元测试
大家好,今天来为大家分享java单元测试是什么的一些知识点,和什么是单元测试的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!
junit是什么
junit是一个Java语言的单元测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例(用于java语言)。
junit由Kent Beck和Erich Gamma建立, JUnit有其自己的JUnit扩展生态圈。多数Java的开发环境已集成了JUnit作为单元测试的工具。用于测试期望结果的断言,用于共享共同测试数据的测试工具,用于方便的组织和运行测试的测试套件及图形和文本的测试运行器。
扩展资料:
Junit测试
Junit测试为程序员测试,即所谓白盒测试,程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。
1、测试计划阶段:根据需求说明书,制定测试进度。
2、测试设计阶段:根据代码的功能,人工设计测试用例进行基本功能测试。依据程序设计说明书,按照一定规范化的方法进行软件结构划分和设计测试用例。
3、测试执行阶段:输入测试用例,得到测试结果。
4、测试总结阶段:对比测试的结果和代码的预期结果,分析错误原因,找到并解决错误。
参考资料来源:百度百科-junit
java怎么做单元测试,紧急!
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。比如可以测试一个类,或者一个类中的一个方法。
以下是测试用例类的基本结构:
public class HelloWorldTest extends TestCase
{
/*
*每次用例执行前要执行的初始化方法
*/
protected void setUp() throws Exception
{
super.setUp();
}
/*
*每次用例执行后要执行的清除功能
*/
protected void tearDown() throws Exception
{
super.tearDown();
}
/*
*一个测试方法,在其中实现对被测单元的调用,并验证
*/
public final void testCalculate()
{
//TODO实现 calculate()。
}
}
JAVA单元测试
首先我们需要先下载相应的 JUnit相关的 JAR包,下载的过程可以去 JUnit的官方网站,也可以直接通过 Maven资源仓库来完成。
使用简单的@Test注解实现我们的测试方法的编写和执行
准备工作做好之后,接下来我们就可以开始尝试编写壹个简单的测试代码了。首先,我们编写了壹个 Calculator类,并提供五个方法分别完成加减乘除以及求平方的运算。代码如下:
package net.oschina.bairrfhoinn.main;
public class Calculator{
public void add(int n){
result+= n;
}
public void substract(int n){
result-= n;
}
public void multiply(int n){
result*= n;
}
public void divide(int n){
result/= n;
}
public void square(int n){
result= n* n;
}
public int getReuslt(){
return result;
}
public void clear(){
result= 0;
}
private static int result;
}
在测试类中用到了JUnit4框架,自然要把相应地Package包含进来。最主要地一个Package就是org.junit.*。把它包含进来之后,绝大部分功能就有了。还有一句话也非常地重要“import static org.junit.Assert.*;”,我们在测试的时候使用的壹系列assertEquals()方法就来自这个包。大家注意壹下,这是壹个静态包含(static),是JDK5中新增添的壹个功能。也就是说,assertEquals是Assert类中的壹系列的静态方法,壹般的使用方式是Assert. assertEquals(),但是使用了静态包含后,前面的类名就可以省略了,使用起来更加的方便。
另外要注意的是,我们的测试类是壹个独立的类,没有任何父类。测试类的名字也可以任意命名,没有任何局限性。所以我们不能通过类的声明来判断它是不是一个测试类,它与普通类的区别在于它内部的方法的声明,我们接着会讲到。在测试类中,并不是每壹个方法都是用于测试的,所以我们必须使用“注解”来明确表明哪些是测试方法。“注解”也是JDK5的壹个新特性,用在此处非常恰当。我们可以看到,在某些方法的前有@Before、@Test、@Ignore等字样,这些就是注解,以壹个“@”作为开头。这些注解都是JUnit4自定义的,熟练掌握这些注解的含义,对于编写恰当的测试类非常重要。
接下来我们创建壹个测试类 CalculatorTest.java,代码如下:
package net.oschina.bairrfhoinn.test;
import static org.junit.Assert.*;
import org.junit.Test;
import net.oschina.bairrfhoinn.main.Calculator;
public class CalculatorTest{
private static Calculator calculator= new Calculator();
@Test
public void testAdd(){
calculator.add(7);
calculator.add(8);
assertEquals(15, calculator.getReuslt());
}
}
首先,我们要在方法的前面使用@Test标注,以表明这是壹个测试方法。对于方法的声明也有如下要求:名字可以随便取,没有任何限制,但是返回值必须为void,而且不能有任何参数。如果违反这些规定,会在运行时抛出壹个异常。至于方法内该写些什么,那就要看你需要测试些什么了。比如上述代码中,我们想测试壹下add()方法的功能是否正确,就在测试方法中调用几次add函数,初始值为0,先加7,再加8,我们期待的结果应该是15。如果最终实际结果也是15,则说明add()方法是正确的,反之说明它是错的。assertEquals(15, calculator.getResult());就是用来判断期待结果和实际结果是否相等,其中第壹个参数填写期待结果,第二个参数填写实际结果,也就是通过计算得到的结果。这样写好之后,JUnit会自动进行测试并把测试结果反馈给用户。
如果想运行它,可以在 eclipse的资源管理器中选择该类文件,然后点击右键,选择 Run As->JUnit Test即可看到运行结果。
使用@Test的属性 Ignore指定测试时跳过这个方法
如果在写程序前做了很好的规划,那么哪些方法是什么功能都应该实现并且确定下来。因此,即使该方法尚未完成,他的具体功能也是确定的,这也就意味着你可以为他编写测试用例。但是,如果你已经把该方法的测试用例写完,但该方法尚未完成,那么测试的时候无疑是“失败”。这种失败和真正的失败是有区别的,因此 JUnit提供了壹种方法来区别他们,那就是在这种测试函数的前面加上@Ignore标注,这个标注的含义就是“某些方法尚未完成,暂不参与此次测试”。这样的话测试结果就会提示你有几个测试被忽略,而不是失败。壹旦你完成了相应函数,只需要把@Ignore标注删去,就可以进行正常的测试。
比如说上面的测试类 Calculator.java中,假设我们的 Calculator类的 multiply()方法没有实现,我们可以在测试类 CalculatorTest中先写如下测试代码:
package net.oschina.bairrfhoinn.test;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Test;
import net.oschina.bairrfhoinn.main.Calculator;
public class CalculatorTest{
private static Calculator calculator= new Calculator();
...//此处代码省略
@Ignore("method square() not implemented, please test this later...")
@Test
public void testSquare(){
calculator.square(3);
assertEquals(9, calculator.getReuslt());
}
}
我们再运行壹次测试,会看到如下结果,从图中可以很明显的看出,方法testSquare()上的@Ignore注解已经生效了,运行时直接跳过了它,而方法testAdd()仍然正常的运行并通过了测试。
使用注解@Before和@After来完成前置工作和后置工作
前置工作通常是指我们的测试方法在运行之前需要做的壹些准备工作,如数据库的连接、文件的加载、输入数据的准备等需要在运行测试方法之前做的事情,都属于前置工作;类似的,后置工作则是指测试方法在运行之后的壹些要做的事情,如释放数据库连接、输入输出流的关闭等;比如我们上面的测试,由于只声明了壹个 Calculator对象,他的初始值是0,但是测试完加法操作后,他的值就不是0了;接下来测试减法操作,就必然要考虑上次加法操作的结果。这绝对是壹个很糟糕的设计!我们非常希望每壹个测试方法都是独立的,相互之间没有任何耦合度。因此,我们就很有必要在执行每壹个测试方法之前,对Calculator对象进行壹个“复原”操作,以消除其他测试造成的影响。因此,“在任何壹个测试方法执行之前必须执行的代码”就是壹个前置工作,我们用注解@Before来标注它,如下例子所示:
package net.oschina.bairrfhoinn.test;
...
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class CalculatorTest{
...//这里省略部分代码
@Before
public void setUp() throws Exception{
calculator.clear();
}
@After
public void tearDown() throws Exception{
System.out.println("will do sth here...");
}
...//这里省略部分代码
}
另外要说的是,注解@Before是定义在 org.junit.Before这个类中的,因此使用时需要将其引入我们的代码中。这样做了之后,每次我们运行测试方法时,JUnit都会先运行 setUp()方法将 result的值清零。不过要注意的是,这里不再需要@Test注解,因为这并不是壹个 test,只是壹个前置工作。同理,如果“在任何测试执行之后需要进行的收尾工作,我们应该使用@After来标注,方法与它类似。由于本例比较简单,不需要用到此功能,所以我们只是简单了给它添加了壹个 tearDown()方法并在收尾时打印壹句话到控制台,并且使用@After来注解这个方法。
使用@BeforeClass和@AfterClass来完成只需要执行壹次的前置工作和后置工作
上面我们提到了两个注解@Before和@After,我们来看看他们是否适合完成如下功能:有壹个类负责对大文件(超过500 MB)进行读写,他的每壹个方法都是对文件进行操作。换句话说,在调用每壹个方法之前,我们都要打开壹个大文件并读入文件内容,这绝对是壹个非常耗费时的操作。如果我们使用@Before和@After,那么每次测试都要读取壹次文件,效率及其低下。所以我们希望的是,在所有测试壹开始读壹次文件,所有测试结束之后释放文件,而不是每次测试都读文件。JUnit的作者显然也考虑到了这个问题,它给出了@BeforeClass和@AfterClass两个注解来帮我们实现这个功能。从名字上就可以看出,用这两个注解标注的函数,只在测试用例初始化时执行@BeforeClass方法,当所有测试执行完毕之后,执行@AfterClass进行收尾工作。在这里要注意壹下,每个测试类只能有壹个方法被标注为@BeforeClass或@AfterClass,而且该方法必须是 public static类型的。
使用@Test的属性 timeout来完成限时测试,以检测代码中的死循环
现在假设我们的 Calculator类中的 square()方法是个死循环,那应该怎么办呢,比如说像下面这样:
public void square(int n){
for(;;){}
}
如果测试的时候遇到死循环,你的脸上绝对不会露出笑容的。因此,对于那些逻辑很复杂,循环嵌套比较深的、有可能出现死循环的程序,因此壹定要采取壹些预防措施。限时测试是壹个很好的解决方案。我们给这些测试函数设定壹个预期的执行时间,超过了这壹时间,他们就会被系统强行终止,并且系统还会向你汇报该函数结束的原因是因为超时,这样你就可以发现这些 Bug了。要实现这壹功能,只需要给@Test标注加壹个参数timeout即可,代码如下:
@Test(timeout=2000L)
public void testSquare(){
calculator.square(3);
assertEquals(9, calculator.getReuslt());
}
timeout参数表明了你预计该方法运行的时长,单位为毫秒,因此2000就代表2秒。现在我们让这个测试方法运行壹下,看看失败时是什么效果。
使用@Test的属性expected来监控测试方法中可能会抛出的某些异常
JAVA中的异常处理也是壹个重点,因此你经常会编写壹些需要抛出异常的函数。如果你觉得壹个函数应该抛出异常,但是它没抛出,这算不算 Bug呢?这当然是Bug,JUnit也考虑到了这壹点,并且可以帮助我们找到这种 Bug。例如,我们写的计算器类有除法功能,如果除数是壹个0,那么必然要抛出“除0异常”。因此,我们很有必要对这些进行测试。代码如下:
@Test(expected=java.lang.ArithmeticException.class)
public void testDivide(){
calculator.divide(0);
}
如上述代码所示,我们需要使用@Test注解中的expected属性,将我们要检验的异常(这里是 java.lang.ArithmeticException)传递给他,这样 JUnit框架就能自动帮我们检测是否抛出了我们指定的异常。
指定 JUnit运行测试用例时的 Runner
大家有没有想过这个问题,当你把测试代码提交给JUnit框架后,框架是如何来运行你的代码的呢?答案就是Runner。在JUnit中有很多个Runner,他们负责调用你的测试代码,每壹个Runner都有其各自的特殊功能,你要根据需要选择不同的Runner来运行你的测试代码。可能你会觉得奇怪,前面我们写了那么多测试,并没有明确指定壹个Runner啊?这是因为JUnit中有壹个默认的Runner,如果你没有指定,那么系统会自动使用默认Runner来运行你的代码。换句话说,下面两段代码含义是完全壹样的:
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class CalculatorTest{
...//省略此处代码
}
//用了系统默认的JUnit4.class,运行效果完全壹样
public class CalculatorTest{
...//省略此处代码
}
什么是单元测试
单元测试的对象是软件设计的最小单位——模块。单元测试的依据是详细设描述,单元测试应对模块内所有重要的控制路径设计测试用例,以便发现模块内部的错误。单元测试多采用白盒测试技术,系统内多个模块可以并行地进行测试。单元测试任务单元测试任务包括:1模块接口测试;2模块局部数据结构测试;3模块边界条件测试;4模块中所有独立执行通路测试;5模块的各条错误处理通路测试。模块接口测试是单元测试的基础。只有在数据能正确流入、流出模块的前提下,其他测试才有意义。测试接口正确与否应该考虑下列因素:1输入的实际参数与形式参数的个数是否相同;2输入的实际参数与形式参数的属性是否匹配;3输入的实际参数与形式参数的量纲是否一致;4调用其他模块时所给实际参数的个数是否与被调模块的形参个数相同;5调用其他模块时所给实际参数的属性是否与被调模块的形参属性匹配;6调用其他模块时所给实际参数的量纲是否与被调模块的形参量纲一致;7调用预定义函数时所用参数的个数、属性和次序是否正确;8是否存在与当前入口点无关的参数引用;9是否修改了只读型参数;10对全程变量的定义各模块是否一致;11是否把某些约束作为参数传递。如果模块内包括外部输入输出,还应该考虑下列因素:1文件属性是否正确;2 OPEN/CLOSE语句是否正确;3格式说明与输入输出语句是否匹配;4缓冲区大小与记录长度是否匹配;5文件使用前是否已经打开;6是否处理了文件尾;7是否处理了输入/输出错误;8输出信息中是否有文字性错误;检查局部数据结构是为了保证临时存储在模块内的数据在程序执行过程中完整、正确。局部数据结构往往是错误的根源,应仔细设计测试用例,力求发现下面几类错误:1不合适或不相容的类型说明;2变量无初值;3变量初始化或省缺值有错;4不正确的变量名(拼错或不正确地截断); 5出现上溢、下溢和地址异常。除了局部数据结构外,如果可能,单元测试时还应该查清全局数据(例如FORTRAN的公用区)对模块的影响。在模块中应对每一条独立执行路径进行测试,单元测试的基本任务是保证模块中每条语句至少执行一次。此时设计测试用例是为了发现因错误计算、不正确的比较和不适当的控制流造成的错误。此时基本路径测试和循环测试是最常用且最有效的测试技术。计算中常见的错误包括:1误解或用错了算符优先级;2混合类型运算;3变量初值错;4精度不够;5表达式符号错。比较判断与控制流常常紧密相关,测试用例还应致力于发现下列错误: 1不同数据类型的对象之间进行比较;2错误地使用逻辑运算符或优先级;3因计算机表示的局限性,期望理论上相等而实际上不相等的两个量相等;4比较运算或变量出错;5循环终止条件或不可能出现;6迭代发散时不能退出;7错误地修改了循环变量。一个好的设计应能预见各种出错条件,并预设各种出错处理通路,出错处理通路同样需要认真测试,测试应着重检查下列问题:1输出的出错信息难以理解;2记录的错误与实际遇到的错误不相符;3在程序自定义的出错处理段运行之前,系统已介入;4异常处理不当;5错误陈述中未能提供足够的定位出错信息。边界条件测试是单元测试中最后,也是最重要的一项任务。众的周知,软件经常在边界上失效,采用边界值分析技术,针对边界值及其左、右设计测试用例,很有可能发现新的错误。单元测试过程一般认为单元测试应紧接在编码之后,当源程序编制完成并通过复审和编译检查,便可开始单元测试。测试用例的设计应与复审工作相结合,根据设计信息选取测试数据,将增大发现上述各类错误的可能性。在确定测试用例的同时,应给出期望结果。应为测试模块开发一个驱动模块(driver)和(或)若干个桩模块(stub),下图显示了一般单元测试的环境。驱动模块在大多数场合称为“主程序”,它接收测试数据并将这些数据传递到被测试模块,被测试模块被调用后,“主程序”打印“进入-退出”消息。驱动模块和桩模块是测试使用的软件,而不是软件产品的组成部分,但它需要一定的开发费用。若驱动和桩模块比较简单,实际开销相对低些。遗憾的是,仅用简单的驱动模块和桩模块不能完成某些模块的测试任务,这些模块的单元测试只能采用下面讨论的综合测试方法。提高模块的内聚度可简化单元测试,如果每个模块只能完成一个,所需测试用例数目将显著减少,模块中的错误也更容易发现。
如果你还想了解更多这方面的信息,记得收藏关注本站。