jUnit测试框架入门详解
入门知识
什么是单元测试
单元测试是针对最小的功能单元编写的测试代码。Java程序最小的功能单元是方法,因此单元测试就是针对单个Java方法的测试。
为什么要使用单元测试
使用main()方法测试的缺点:
只能有一个main()方法,不能把测试代码分离,且也没有打印出测试结果和期望结果;另外也不会生成批量的测试报告,测试流程不规范。因此,我们需要引入一种测试框架,以帮助我们编写测试用例。
单元测试的好处:
一是能确保单个方法运行正常,运行结果符合预期;二是如果修改了代码,只需要确保其对应的单元测试通过;三是测试代码本身就可以作为实例代码;四是可以自动化运行所有测试并获得报告。
Junit单元测试框架介绍
JUnit是一个开源的Java语言的单元测试框架,其专门针对Java语言设计,使用十分广泛;JUnit已成事实上的标准单元测试框架(行业标准)。
使用JUnit的优点(特点)
- 可以使用断言(Assertion)测试期望结果;
- 可以方便的用来对方法进行测试
- 可以方便地组织和运行测试
- 可以方便地查看测试结果
- 常用IDE(例如Intellil ldea 、eclipse)都集成了JUnit
- 可以方便地集成到Maven。
- 可以灵活的编写测试代码,可以针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立。
- 不需要程序员去分析测试的结果,会自动生成测试报告出来。
JUnit设计的测试架构
- TestCase:一个TestCase表示一个测试;
- TestSuite:一个TestSuite包含一组TestCase,表示一组测试
- TestFixture:一个TestFixture表示一个测试环境
- TestResult:用于收集测试结果;
- TestRunner:用于运行测试;
- Testlistener:用于监听测试过程,手机测试数据;
- Assert:用于断言测试结果是否正确。
需求
某个系统,有多个业务方法,请使用Junit单元测试框架,编写测试代码,完成对这些方法的正确性测试。
断言机制
程序员可以通过预测业务方法的结果。Assert工具类表示断言。常用的方法为Assert.assertEquals()、Assert.assertNotNull()等。
Assert断言常用方法:
- 断言相等:assertEquals(100,x);
- 断言不相等:assertNotEquals(100,x);
- 断言数组相等:assertArrayEquals({1,2,3},X);
- 浮点数断言相等:assertEquals(3.1416,x,0.0001); (第三个参数为精度设置)
- 断言为null: assertNull(x);
- 断言为非null:assertNotNull
- 断言为true/false: assertTrue(x>0) assertFalse(x<0)
jUnit基础知识小结
1、一个TestCase一般包含有一组相关的测试方法;
2、使用断言测试结果(注意浮点数assertEquals要指定delta,即精度)
3、每个测试方法必须完全独立;
4、测试代码必须非常简单;
5、不能为测试代码再编写测试
6、严谨性要求:测试需要覆盖各种输入条件,特别是边界条件。
jUnit具体使用步骤
①将Junit框架的jar包导入到项目中(注意:IDEA集成了Junit框架,不需要我们自己手工导入了)
②为需要测试的业务类,定义对应的测试类,并为每个业务方法,编写对应的测试方法(必须:公共、无参、无返回值),Idea支持自动生成测试用例(在idea中将光标置于要测试的类名中,按下Ctrl+Shift+T,即可弹出添加测试用例的对话框)
③测试方法上必须声明@Test注解,然后在测试方法中,编写代码调用被测试的业务方法进行测试;
④开始测试:选中测试方法,右键选择“JUnit运行”,如果测试通过则是绿色;如果测试失败,则是红色
jUnit常用注解
Junit单元测试框架的常用注解(Junit 4.xxxx版本)
注解 | 说明 |
@Test | 测试类中的方法必须用它修饰才能成为测试方法,才能启动执行 |
@Before | 用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。 |
@After | 用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。 |
@BeforeClass | 用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。 |
@AfterClass | 用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。 |
●在测试方法执行前执行的方法,常用于:初始化资源。
●在测试方法执行完后再执行的方法,常用于:释放资源。
使用@Before和@After
@Before在每一个@Test测试方法执行前执行,@After在每一个@Test方法后执行。
对于同一个单元测试内的多个测试方法:测试前都需要初始化某些对象,测试后可能需要清理资源;对于这种需求Junit使用@Before和@After实现,在@Before方法中初始化测试资源,在@After方法中释放测试资源。
@Test的执行过程
JUnit对每个@Test方法:(执行过程)
- 1、实例化XXXTest测试类(每一个@Test都会创建一次XXXTest类);
- 2、执行@Before方法;
- 3、执行@Test方法;
- 4、执行@After方法。注意:使用@Before和@After可以保证:
- 单个@Test方法执行前会创建新的XxxTest实例;实例变量的状态不会传递给下一个@Test方法。
- 单个@Test方法执行前后会执行@Before和@After方法。
使用@BeforeClass和@AfterClass静态方法(过程):
1、在执行所有@Test方法前执行@BeforeClass标注的静态方法;
2、执行所有测试
3、在执行所有@Test方法后执行@AfterClass静态方法。
注意:
- @BeforeClass静态方法初始化的对象只能存放在静态字段中,静态字段的状态会影响到所有的@Test
- @BeforeClass在XXXTest测试类的构造器之前执行;@AfterClass方法在@After方法后执行。
@Before、@After、@Beforedass、@AfterClass使用场景
- @Before:初始化测试对象;例如:input=new FilelnputStream();
- @After:销毁@Before创建的测试对象,;例如:input.Close();
- @BeforeClass:初始化非常耗时的资源,例如:创建数据库。
- @AfterClass:清理@BeforeClass创建的资源,例如:删除数据库。
理解JUnit执行测试的生命周期
1、@Before用于初始化测试对象,测试对象以实例变量存放;
2、@After用于清理@Before创建的对象
3、@BeforeClass用于初始化耗时资源,以静态变量存放;
4、@AfterClass用于清理@BeforeClass创建的资源。
Junit单元测试框架的常用注解(Junit 5.Xxxx版本)
注解 | 说明 |
@Test | 测试类中的方法必须用它修饰才能成为测试方法,才能启动执行 |
@BeforeEach | 用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。 |
@AfterEach | 用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。 |
@BeforeAll | 用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。 |
@AfterAll | 用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。 |
●开始执行的方法:初始化资源。
●执行完之后的方法:释放资源。
jUnit单元测试
异常测试
对可能抛出的异常进行测试:
异常本身是方法签名的一部分:
public static int parselnt() throws NumberFormatException
测试错误的输入是否导致特定的异常
Integer.parselnt(null);
Integer.parselnt(“”);
Integer.parselnt("xyz");
如何测试异常
我们可以通过try-catch测试,但这样会写出很多这样的语句,从而使其变得复杂起来;更好的方法就是使用expected测试异常,具体操作如下:
@Test(expected=NumberFormatException.class)
public void testNumberFormat(){
Integer.parselnt(null);
}
总结:
1、测试异常可以使用@Test(expected=Exception.class)
2、对可能发生的每种类型的异常进行测试。
超时测试
可以为JUnit的单个测试设置超时:
超时设置为1秒:@Test(timeout=1000)【timeout单位是毫秒】。如果测试方法执行时间小于超时设置的时间,测试通过;反之测试不通过。
注意:超时测试不能取代性能测试和压力测试。
参数化测试
1、参数化测试:如果待测试的输入和输出是一组数据:
-可以把测试数据组织起来;
-用不同的测试数据调用相同的测试方法。
2、参数化测试要求
-参数必须有静态方法data()返回,返回类型为Collection<?>,静态方法必须标记为@Parameters;
-测试类必须标记为:@RunWith(Parameterized.class);
-构造方法参数必须和测试参数对应。
@RunWith(Parameterized.class)
public class DemoAbsTest {
@Parameters
public static Collection<?> data(){
return Arrays.asList(new Object[][]{
{0,0},{1,1},{-1,1}
});
}
int input;
int expected;
public DemoAbsTest(int input,int expected){// 构造方法
this.input =input;
this.expected =expected;
}
@Test
public void testAbs(){
int r=Math.abs(this.input);
assertEquals(this.expected,r);
}
}