单元测试
什么是单元测试
- 单元测试是针对最小功能单元编写测试代码
- Java程序最小的功能单元是方法
- 单元测试针对单个Java方法的测试
测试驱动开发TDD
- Test-Driven Development
- 编写接口
- 编写测试
- 编写实现
- 运行测试
- NO 编写实现
- YES 任务完成
JUnit
- 开源的Java单元测试框架
- 标准单元测试框架
JUnit特点
- 使用断言测试期望结果
- 方便地组织和运行测试
- 方便查看测试结果
JUnit设计
- TestCase: 一个TestCase表示一个测
- TestSuite:一个TestSuite包含一组TestCase,表示一组测试
- TestFixture:一个TestFixture表示一个测试环境
- TestResult:用于收集测试结果
- TestRunner:用于运行测试
- TestListener:用于监听测试过程,收集测试数据
- Assert:用于断言测试结果是否正确
基础注解
2A2B
- @Before:初始化测试对象,例如:input = new FilelnputStream();
- @After:销毁@Before创建的测试对象,例如:input.close();
- @BeforeClass:初始化非常耗时的资源,例如︰创建数据库
- @AfterClass:清理@BeforeClass创建的资源,例如︰删除数据库
总结
@Before用于初始化测试对象,测试对象以实例变量存放
@After用于清理@Before创建的对象
@BeforeClass用于初始化耗时资源
@AfterClass用于清理@BeforeClass创建的资源
@BeforeClass和@AfterClass静态方法
beforeClass(): 方法首先执行,并且只执行一次。
afterClass():方法最后执行,并且只执行一次。
before():方法针对每一个测试用例执行,但是是在执行测试用例之前。
after():方法针对每一个测试用例执行,但是是在执行测试用例之后。
在 before() 方法和 after() 方法之间,执行每一个测试用例。
前因
在同一个单元测试内有多个测试方法,
因为在测试前都需要初始化某些对象,Calculator calc=new Calculator();
测试后还有可能需要清理资源,fileInputStream.close();
后果
junit中使用before和after注解
- @Before 在所在方法中初始化测试资源
- @After 在所在方法中释放测试资源
package sour;
public class Calculator {
public int calculate(String expression) {
String[] ss = expression.split("\\+");
int sum = 0;
for (String s : ss) {
// trim()的作用是去掉字符串两端的多余的空格,
sum = sum + Integer.parseInt(s.trim());
}
return sum;
}
}
package Tests;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import sour.Calculator;
public class CalculatorTest1 {
Calculator calc;
@Before
public void setUp() {
calc = new Calculator();
System.out.println("@Before");
}
@Test
public void testCalcAdd2Numbers() {
int r = calc.calculate("1+2");
assertEquals(3, r);
System.out.println("1");
}
@Test
public void testCalcAdd3Numbers() {
int r = calc.calculate("1+2+5");
assertEquals(8, r);
System.out.println("2");
}
@Test
public void testCalcAddLargeNumber() {
int r = calc.calculate("123+456");
assertEquals(579, r);
System.out.println("3");
}
@Test
public void testCalcWithWhiteSpace() {
int r = calc.calculate("1 + 5 + 10 ");
assertEquals(16, r);
System.out.println("4");
}
@After
public void tearDown() {
calc = null;
System.out.println("@After");
}
}
junit执行逻辑
package Tests;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class CaculatorTest3 {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("@BeforeClass");
}
@AfterClass
public static void tearDownBeforeClass() throws Exception {
System.out.println("@AfterClass");
}
@Before
public void setUp() throws Exception {
System.out.println(" @Before");
}
@After
public void tearDown() throws Exception {
System.out.println(" @After");
}
@Test
public void test1() throws Exception {
System.out.println(" 测试方法1");
}
@Test
public void test2() throws Exception {
System.out.println(" 测试方法2");
}
@Test
public void test3() throws Exception {
System.out.println(" 测试方法3");
}
}
断言
断言类型
void assertEquals(boolean expected, boolean actual):检查两个变量或者等式是否平衡
void assertTrue(boolean expected, boolean actual):检查条件为真
void assertFalse(boolean condition):检查条件为假
void assertNotNull(Object object):检查对象不为空
void assertNull(Object object):检查对象为空
void assertSame(boolean condition):assertSame() 方法检查两个相关对象是否指向同一个对象
void assertNotSame(boolean condition):assertNotSame() 方法检查两个相关对象是否不指向同一个对象
void assertArrayEquals(expectedArray, resultArray):assertArrayEquals() 方法检查两个数组是否相等
- import static org.junit.Assert.*;
参数化/数据驱动
用 @RunWith(Parameterized.class) 来注释 test 类。
创建一个由 @Parameters注释的公共的静态方法,它返回一个对象的集合(数组)来作为测试数据集合。
创建一个公共的构造函数,它接受和一行测试数据相等同的东西。
为每一列测试数据创建一个实例变量。
用实例变量作为测试数据的来源来创建你的测试用例。
https://github.com/junit-team/junit/wiki/Parameterized-tests
测试套件
测试套件意味着捆绑几个单元测试用例并且一起执行他们。在 JUnit 中,@RunWith和@Suite注释用来运行套件测试。
测试优先级
写在class上面
- @FixMethodOrder(MethodSorters.DEFAULT) //默认的顺序
- @FixMethodOrderMethod(Sorters.NAME_ASCENDING) //按方法名字母顺序执行
- @FixMethodOrder(MethodSorters.JVM) // 指定测试方法按定义的顺序执行 按照JVM得到的方法顺序,也就是代码中定义的方法顺序
异常
测试代码是否它抛出了想要得到的异常。expected 参数和 @Test 注释一起使用。
@Test(expected = ArithmeticException.class)
TestRunner内置方法
编码规范
类名: 定义测试类,类名是由被测试类名Test构成。例如:CalculatorTest
包名: 定义的测试类需要放在xxx.xxx.xxx.test包中。例如:package com.mylifes1110.test;
方法名: 测试方法的方法名有两种定义方式test测试方法和测试方法。例如:testAdd和add
返回值: 因为我们的方法只是在类中测试,可以独立运行,所以不需要处理任何返回值,所以这里使用void。例如:public void add();
参数列表: 因为我们的方法是用来测试的,至于参数列表的传入是没有必要的。我们在测试的时候自行传入需要的参数测试即可。所以在此参数列表为空。例如:例如:public void add();
@Test注解: 测试是需要运行来完成的。如果我们只有一个main方法,显然在结构上还是需要我们去注释掉测试过的。解决此问题这里我们需要在测试方法上方加@Test注解来完成测试,只要是加该注解的方法,可以单独运行此方法来完成测试。