什么是单元测试
简单的说: 单元测试是为了测试某一个代码单元而写的测试代码;
什么叫“一个代码单元”呢?是一个模块、还是一个类、还是一个方法(函数)呢?
在面向对象编程中,是为了测试某一个类的某一个方法能否正常工作,而写的测试代码。
单元测试不是集成测试
这里需要强调一个观念,那就是单元测试只是测试一个方法单元,它不是测试一整个流程。
两种函数(方法),两种不同的测试方式
一个类的方法可以分为两种,一种是有返回值的,另一种是没有返回值的。
为什么写单元测试
首先跑一次单元测试总比运行一次app快
写完一部分功能独立的代码,就能立刻看到他们是不是正确的
减少大部分手工测试
更快的发现bug
并发现更多的bug
测试驱动开发(TDD) ,提高开发效率
觉的没有时间写测试代码?
怎么写单元测试
我们先不说测试代码怎么写,先搞清楚流程
刚才说了,单元测试是为了测试某一个类的某一个方法能否正常工作,而写的测试代码,
那我们写单元测试代码,就是给每一个java代码类的public方法写对应的测试代码;
那么非public方法怎么办呢, 一般来说,是不做处理的, 非public方法通常是类的内部实现细节,我们一般只关心public方法的的输入和输出;
一般来说写单元测试代码分为三个部分
准备工作 : 一般先要new出你要的测试的类的对象
执行操作 : 然后写测试代码
验证结果 : 得到验证结果,看是否达到预期
注意事项: 单元测试不会接触到数据库,不会接触到网络,不会接触到一些复杂的外部环境,如果有的话,那可能是你测试的方式有误,测试的粒度不够“单元”
刚才上面说到
一个类的方法可以分为两种,一种是有返回值的,另一种是没有返回值的。
先说有返回值的
JUnit单元测试框架的使用
单元测试,一般都会用到一个或多个单元测试框架,在这里,我们介绍一下JUnit4这个测试框架。这是Java界用的最广泛,也是最基础的一个框架,其他的很多框架都是基于或兼容JUnit4的。
为什么要使用单元测试框架
首先你也可以不用测试框架, 手工写测试代码, java 中可以使用main方法执行测试代码,你可以自己写测试代码,然后执行
有下面的这段代码需要进行测试
public Boolean loginApp(String name){
if (name == "123456") {
return true;
}else {
return false;
}
}
我们看看在不使用JUnit测试框架的情况下怎么怎么测试
public static void main(String[] args) {
LoginPersenter loginPersenter = new LoginPersenter();
Boolean aBoolean = loginPersenter.loginApp("123456");
if(aBoolean == true) {
System.out.println("登录成功了");
} else {
System.out.println("登录失败了");
}
}
那么我们使用JUnit测试框架的情况下
@Test
public void testAppLogin() throws Exception{
LoginPersenter loginPersenter = new LoginPersenter();
Boolean aBoolean = loginPersenter.loginApp("123456");
assertTrue(aBoolean);
}
每一个被测试的方法,写一个对应的测试方法, 通过@Test注解来标识
先来看看JUnit注解
注解
描述
@Test public void method()
简单说就是用这个注解的代表的是一个测试用例
@Before public void method()
Before注释表示,该方法必须在类中的每个测试之前执行,以便执行测试某些必要的先决条件。
@BeforeClass public static void method()
BeforeClass注释指出这是附着在静态方法必须执行一次并在类的所有测试之前。发生这种情况时一般是测试计算共享配置方法(如连接到数据库)。
@After public void method()
After 注释指示,该方法在执行每项测试后执行(如执行每一个测试后重置某些变量,删除临时变量等)
@AfterClass public static void method()
当需要执行所有的测试在JUnit测试用例类后执行,AfterClass注解可以使用以清理建立方法,(从数据库如断开连接)。注意:附有此批注(类似于BeforeClass)的方法必须定义为静态。
@Ignore public static void method()
当想暂时禁用特定的测试执行可以使用忽略注释。每个被注解为@Ignore的方法将不被执行。
然后看看JUnit断言
断言
描述
void assertEquals([String message], expected value, actual value)
断言两个值相等。值可能是类型有 int, short, long, byte, char or java.lang.Object. 第一个参数是一个可选的字符串消息
void assertTrue([String message], boolean condition)
断言一个条件为真
void assertFalse([String message],boolean condition)
断言一个条件为假
void assertNotNull([String message], java.lang.Object object)
断言一个对象不为空(null)
void assertNull([String message], java.lang.Object object)
断言一个对象为空(null)
void assertSame([String message], java.lang.Object expected, java.lang.Object actual)
断言,两个对象引用相同的对象
void assertNotSame([String message], java.lang.Object unexpected, java.lang.Object actual)
断言,两个对象不是引用同一个对象
void assertArrayEquals([String message], expectedArray, resultArray)
断言预期数组和结果数组相等。数组的类型可能是 int, long, short, char, byte or java.lang.Object.
fail()
让测试方法失败
看完这些东西 ,我们写个代码应用一下
先看一下等待测试的代码
package com.zhiguo.dagger2test;
/**
* Created by TiaoPi on 2017/11/20.
*/
public class JUnitTest {
public int testAdd(int a ,int b){
return a + b;
}
public Boolean testEquals(int a ,int b){
if (a == b) {
return true;
}else {
return false;
}
}
}
然后看一下测试代码
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
JUnitTest jUnitTest;
int testAddNum ;
@Before
public void setup() {
jUnitTest = new JUnitTest();
testAddNum = 2;
}
@After
public void executedAfterEach(){
testAddNum = 2;
}
@Test
public void testAdd() throws Exception{
int testAdd = jUnitTest.testAdd(1, 2);
assertEquals(testAddNum + 1,testAdd);
// assertEquals("测试得到的结果是不是" +testAddNum + 1 ,testAddNum + 1,testAdd);
}
@Test
public void testAdd2() throws Exception{
int testAdd = jUnitTest.testAdd(2, 2);
assertEquals(testAddNum + 2,testAdd);
// assertEquals("测试得到的结果是不是" +testAddNum + 2 ,testAddNum + 2,testAdd);
}
@Test
public void testEquals() throws Exception{
Boolean aBoolean = jUnitTest.testEquals(1, 1);
assertTrue(aBoolean);
// assertTrue("测试得到的结果不是true",aBoolean);
}
@Test
@Ignore("不让testIgnore方法执行")
public void testIgnore() {
}
}
开始执行
1f844e5d-4aeb-497f-989a-4693f8d05b56.png
执行完成后,没有问题的情况下
d69996ec-0b6b-46e6-9e04-077554724a93.png
我们搞几个问题出来
4964d84f-e022-4ab1-93e6-40b87ffd8317.png
其他的功能介绍
Ignore一些测试方法
让JUnit忽略某些方法,让它在跑所有测试方法的时候不要跑这个测试方法。要达到这个目的也很简单,只需要在要被忽略的测试方法前面加上@Ignore就可以了
@Test
@Ignore("不让testIgnore方法执行")
public void testIgnore() {
}
13592a67-cae4-4a21-ae6f-8ca32e656590.png
验证方法会抛出某些异常
有的时候,抛出异常是才能让一个方法正常运行。
比如我们现在有这样一段代码
public int testExpected (int a){
if (a == 1) throw new IllegalArgumentException("这个值不能是1");
return a;
}
进行测试
@Test(expected = IllegalArgumentException.class)
public void testExpected (){
jUnitTest.testExpected(1);
}
当然啦,如果正确的抛出异常是说明代码没问题, 只有抛出异常的时候才会报错
接下来 我们考虑测试没有返回值的方法