Android 开发 单元测试 (JUnit 4)

参考文章 : 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() {
    }

}

开始执行

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);
    }

当然啦,如果正确的抛出异常是说明代码没问题, 只有抛出异常的时候才会报错

接下来 我们考虑测试没有返回值的方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,597评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,577评论 18 399
  • 图、文/孝恩 心中总有棵长寿花独为爹、娘绽放,只因一生当中,唯有他们给予的等待最多、最长、最暖... 住在娘胎十月...
    孝蒽阅读 267评论 4 3
  • 与其纠结画不出,那就不如速涂
    澍叁阅读 386评论 12 9
  • 对于婚姻中中的一些问题,其中最常见的一个角色便是:有一个重要的角色失衡了! 这个角色就是女人的角色!女人就像水,像...
    墨名棋妙001阅读 407评论 0 1