参考文章 : http://chriszou.com/2016/06/07/android-unit-testing-everything-you-need-to-know.html
什么是单元测试
简单的说: 单元测试是为了测试某一个代码单元而写的测试代码;
什么叫“一个代码单元”呢?是一个模块、还是一个类、还是一个方法(函数)呢?
在面向对象编程中,是为了测试某一个类的某一个方法能否正常工作,而写的测试代码。
单元测试不是集成测试
这里需要强调一个观念,那就是单元测试只是测试一个方法单元,它不是测试一整个流程。两种函数(方法),两种不同的测试方式
一个类的方法可以分为两种,一种是有返回值的,另一种是没有返回值的。
为什么写单元测试
- 首先跑一次单元测试总比运行一次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() {
}
}
开始执行
执行完成后,没有问题的情况下
我们搞几个问题出来
其他的功能介绍
Ignore一些测试方法
让JUnit忽略某些方法,让它在跑所有测试方法的时候不要跑这个测试方法。要达到这个目的也很简单,只需要在要被忽略的测试方法前面加上@Ignore
就可以了
@Test
@Ignore("不让testIgnore方法执行")
public void testIgnore() {
}
验证方法会抛出某些异常
有的时候,抛出异常是才能让一个方法正常运行。
比如我们现在有这样一段代码
public int testExpected (int a){
if (a == 1) throw new IllegalArgumentException("这个值不能是1");
return a;
}
进行测试
@Test(expected = IllegalArgumentException.class)
public void testExpected (){
jUnitTest.testExpected(1);
}
当然啦,如果正确的抛出异常是说明代码没问题, 只有抛出异常的时候才会报错