[JAVA]单元测试:从零开始的JUnit之路(Elicpse/IDEA)
来源:互联网 发布:微信java通用版1.0精简 编辑:程序博客网 时间:2024/06/05 20:02
>什么是单元测试
在工程中,我们可能会有很多类和类的方法。单元测试就是对这些类或方法(最小软件测试单元)进行检查和验证,通过给定的测试样例进行覆盖测试。
一般情况下,很多程序员都不写单元测试,这是因为:
- 业务逻辑太过于简单,如add(int a, int b){return a+b;},觉得没有写测试的价值;
- 代码繁琐,如果没有Genenator进行模板的自动书写,那么编写单元测试类将耗费大量时间,耽误工程的开发进度;
- 不会写或者懒得写;
一个简单的单元测试结果如下:
从这个结果中,我们可以快速找到系统中出错的类(T3FTest)和出错的方法(Divide)以及实际测试值和期望值、每个测试单元的运行时间。
>什么是JUnit?
JUnit是当下最流行的单元测试平台。JUnit4主要基于JDK5提供的反射机制,因此需要JDK5以上;而JUnit5则结合了JDK8的lambda表达式,因此需要在JDK8以上运行。由于JUnit5只是在JUnit4的基础上加入了一些新特性以及加入、调整了核心包,对于一般用户而言,总的来说差别不大。此处我们将主要利用JUnit4进行样例演示。
1.获取JUnit和简单使用
请从这里获取JUnit的包:http://junit.org/ 。当然,本文样例所用jar包可以到这里打包下载地址:http://download.csdn.net/download/shenpibaipao/10127109
无论是Eclipse或是IDEA,导入相关的包之后,可以通过注解@Test标注一个方法,使其成为一个测试单元。如:
import org.junit.Test;public class T3F {public int add(int x,int y){return x+y;}@Testpublic void testUnit() throws Exception{System.out.println("这是一个测试单元");}public int divide(int x,int y){return x/y;}}这样,就可以单独执行这个方法,进行一些测试,而无需给出静态main入口去测试:
2.测试类
在原型类中给每一个方法(必须是public void无参方法,暂时略过,详见下)标注@Test显然不是一个好的选择,其一是使得代码更复杂,其二是使得原系统/工程的运行变慢(注解机制消耗机能),且在工程上线发布后,并不需要把这些测试方法一起发布。
因此,在Java等OOP开发中,我们可以编写测试类,专门用于对某些类进行测试。
测试类的命名一般按以下规则处理:
- 测试类类名用:原类名+Test
- 测试方法名用:test+原方法名
这些命名规则是非必须的,但为了使得代码更易读,我们最好都这样命名。
对于上面给出的T3F类的add和devide方法,我们可以编写以下测试类:
package test;import org.junit.Ignore;import org.junit.Test;import org.junit.Before; import org.junit.After; /** * test.T3F Tester.* * @author <身披白袍'Blog AT http://blog.csdn.net/shenpibaipao> * @since <pre>十一月 21, 2017</pre> * @version 1.0 */ public class T3FTest { @Beforepublic void before() throws Exception {}@Afterpublic void after() throws Exception {}/**** Method: add(int x, int y)**/@Ignore("Not Ready to Run")@Testpublic void testAdd() throws Exception {//TODO: Test goes here...}/**** Method: divide(int x, int y)**/@Testpublic void testDivide() throws Exception {//TODO: Test goes here...}}
3.自动生成测试类模板
一定有人会说了,每个方法都要写这么一大堆,烦死了。那么有没有一款插件可以自动帮我们生成这样一堆模板呢?
答案是肯定的。我们以IDEA举例:
- 点击File-->settings-->Plguins-->Browse repositories-->查找JUnit Generator V2.0并安装-->重启IDEA。
这时候,点选我们刚刚的T3F类,利用快捷键Alt+Insert或右键->Generate..,会出现以下窗口:
我们以JUnit4为例,点选该选项后,会自动创建一个test包,并在该包内建立相应的T3FTest.java,该文件的内容如上所示。
注意:打开该T3FTest.java,可能会提示你包名不对、导包不正确等问题,你可以利用alt+enter快捷键手动进行修复、import class、copy junit4 to lib。
>如何进行测试?
JUnit依赖与注解进行测试。在JUnit中测试单元注解主要有以下几种:
- @Test 被该注解标注的方法必须是public void的(下同),标示着该方法为一个测试用例。
- @Before 在每个@Test方法前都会先执行该@Before注解标志的方法。
- @After 与@Before类似,只不过是在@Test方法之后执行。
- @BeforeClass 标注在静态方法上,将在所有@Test前执行且只执行一次。
- @AfterClass 与@BeforeClass类似,只不过在所有@Test之后执行一次。
- @Ignore 被该注解标记的@Test方法,将暂时不进行测试。
package test;import org.junit.Ignore;import org.junit.Test;import org.junit.Before; import org.junit.After; /** * test.T3F Tester.* * @author <身披白袍'Blog AT http://blog.csdn.net/shenpibaipao> * @since <pre>十一月 21, 2017</pre> * @version 1.0 */ public class T3FTest { @Beforepublic void before() throws Exception {System.out.println("测试前");}@Afterpublic void after() throws Exception {System.out.println("测试后");}@Ignore("add被暂时无视")@Testpublic void testAdd() throws Exception {System.out.println("开始测试add()");}@Test(timeout = 1000)public void testDivide() throws Exception {System.out.println("开始测试divide()");}@Testpublic void testMain() throws Exception {System.out.println("开始测试main()");}}在运行该测试类后,它的输出为:
上面讲述了如何让标注一个测试单元。要让一个测试单元真正起效,我们还需要用到“断言”。在JUnit4中,断言主要有以下几种:(一些被废弃的方法我们将不再提):
- assertEquals(expected, actual, delta) 判断两个值是否相等。其中,expected是期待值(正确值)、actual是实际值(测试值)、delta是测试允许误差。
- assertArrayEquals(String message, Object[] expecteds, Object[] actuals) 判断两个数组是否完全相同,若不相同将返回message作为提示信息。
- assertTrue 和 assertFalse 判断真值和假值。
- assertNull 和 assertNotNull 方法测试一个变量是否为空或不为空(null)。
- assertSame 和 assertNotSame 方法测试两个对象引用指向完全相同的对象(也就是比较引用是否相同)。
由于JUnit还用到了匹配器Hamcrest,可以通过assertThat等方法指定一你的检测方法。关于Hamcrest,可以查看:http://hamcrest.org/JavaHamcrest/。关于断言,还可以查看官方的Demo:https://github.com/junit-team/junit4/wiki/Assertions
断言都是org.junit.Assert类的静态方法,可以通过如org.junit.Assert.assertEquals(5, 2+3, 0);的方法调用。我们来举个例子——如何测试T3F类中的add()方法:
/**** Method: add(int x, int y)**/@Testpublic void testAdd() throws Exception {System.out.println("开始测试add()");T3F t3F = new T3F();org.junit.Assert.assertEquals(5,t3F.add(2,3),0);//一个测试数据 2+3是否等于5}如果检测不通过,那么将会出现以下结果:
>参数化覆盖测试和套件测试
经过以上步骤,我们已经能对某一组数据和个别类分开测试了。那能不能直接进行多个类和多组数据的测试呢?
1.参数化测试
我们现在添加一个类:
public class TM {public int sub(int a,int b){return a-b;}}并给这个类加上相应的参数化测试类:
package test;import org.junit.Test;import org.junit.Before; import org.junit.After;import org.junit.runner.RunWith;import org.junit.runners.Parameterized;import java.util.Arrays;import java.util.Collection;/*** ft.TM Tester.** @author <身披白袍'Blog AT http://blog.csdn.net/shenpibaipao>* @since <pre>十一月 21, 2017</pre>* @version 1.0*///1.标注为参数化测试类@RunWith(Parameterized.class)public class TMTest {private int expected;private int a;private int b;/**** Method: sub(int a, int b)**/@Testpublic void testSub() throws Exception {org.junit.Assert.assertEquals(expected,new TM().sub(a,b));}//2.一个构造方法,用于读取测试数据public TMTest(int expectedResult, int firstNumber, int secondNumber) {this.expected = expectedResult;this.a = firstNumber;this.b = secondNumber;}//3.一个静态的测试数据集,并标注为 @Parameters@Parameterized.Parameterspublic static Collection addedNumbers() {return Arrays.asList(new Integer[][] { { 1, 2, 1 }, { 2, 5, 3 },{ 7, 11, 4 } });}}测试结果为:
一个参数化测试类需要有以下要素:
- 标注为参数化测试类:@RunWith(Parameterized.class)
- 一个构造方法,用于读取测试数据
- 一个静态的测试数据集,并标注为 @Parameters
此时我准备同时测试TM和T3F类,该怎么办呢?
我们创建一个套件测试类:
package test;import org.junit.runner.RunWith;import org.junit.runners.Suite;@RunWith(Suite.class)@Suite.SuiteClasses({ T3FTest.class, TMTest.class })//把刚刚写好的两个测试类作为参数public class SuitTest {}测试结果为:
>一些常见的测试要求
1.超时检测
对于某些具有运行时长要求的单元,可以标注这个单元的最长限时(单位为ms):
@Test(timeout = 1000)public void testMethod() throws Exception {//TODO: Test goes here...}
2.异常免疫
有些方法可能会抛出异常,而我们在做测试时希望对这些异常脱敏(比如在MVC开发中我们故意抛出的运行时异常),不希望这些异常打断我们的测试,我们可以这样标注我们的测试单元:
@Test(expected = YourExceptionName.class)public void testMethod() throws Exception {//TODO TEST...}
- [JAVA]单元测试:从零开始的JUnit之路(Elicpse/IDEA)
- Java单元测试之junit
- Java 单元测试利器之 Junit
- Java单元测试之JUnit篇
- JUnit单元测试--IntelliJ IDEA
- JUnit单元测试--IntelliJ IDEA
- JUnit单元测试--IntelliJ IDEA
- Java的单元测试(Junit)
- Junit单元测试的注意要领---看《单元测试之Junit》有感
- Junit单元测试的注意要领---看《单元测试之Junit》有感
- 单元测试之道——基于junit的java单元测试 的读书笔记与思考
- IDEA 运行junit单元测试方法
- idea安装单元测试JUnit插件
- 单元测试学习之二-JAVA的单元测试软件JUnit及覆盖度分析软件DJUnit
- Java单元测试进阶之单元测试利器JUnit(新手上路)
- Java单元测试进阶之单元测试利器JUnit(测试自动化)
- 使用 JUnit 进行 Java 代码的单元测试
- 使用 JUnit 进行 Java 代码的单元测试
- dwz框架常用记录
- 基于SnapDragonBoard410c的远程防盗系统 (二)
- MySQL 主从复制详解(详细)
- 关于性能优化问题的探究
- LeetCode 46. Permutations
- [JAVA]单元测试:从零开始的JUnit之路(Elicpse/IDEA)
- 深度学习框架Keras学习系列(一):线性代数基础与numpy使用(Linear Algebra Basis and Numpy)
- 三级缓存
- 自定义video
- 莫烦PyTorch学习笔记(一)——Torch或Numpy
- 面试题总结(1)
- 《集体智慧编程》数学公式
- less常用
- 如何在 Azure 中均衡 Windows 虚拟机负载以创建具有高可用性的应用程序