单元测试之junit篇

简介

关于单元测试的工具调研可以参考:https://km.sankuai.com/page/365031302

在构建本地单元测试的时候,JUnit4测试框架是java标准测试库,junit测试框架可以让你在编写测试代码的中进行setup, 卸载, 和断言等操作。构建本地单元测试框架运行不需要依赖于真实设备或者模拟设备,可以通过Robolectric库来实现对Android系统框架的依赖,Robolectric库是可以兼容junit库的。

通过junt4进行本地单元测试,不要依赖于android运行环境,因此运行速度更快,可以配合Truth库快速测试某个方法是否符合预期的程序设计。在编写测试代码的时候,可以按照业务实现类来新建测试类,每个Junit4测试类对应一个需要测试的业务代码,每个被@Test注解的测试方法是需要被测试的public方法用于验证业务功能等。

测试环境搭建

在程序中引入junit库,在moudule的build.gradle中配置,其中truth库是为了断言使用。

testImplementation 'junit:junit:4.12'
//断言库,替换junit的api
testImplementation "com.google.truth:truth:1.0.1"

在 Android Studio 项目中,将本地单元测试的源文件存储在 module-name/src/test/java/ 目录下,通常在新建完项目以后,该目录会自动创建,并且会存在一个默认的测试用例代码。

代码目录结构如下:

module-name/src

├── androidTestjava (插桩单元测试、Espresso测试)

├── main/java (业务代码)

├── test/java (本地单元测试)

public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() {
        assertEquals(4, 2 + 2);
    }
}

常见API:参阅文档 JUnit annotations 和 Android annotations.

@Before: 使用这个注解可以指定一段包含测试设置操作的代码。测试类在每个测试执行前调用这段代码。你可以定义多个带有@Before注解的方法, 但是在测试类中这个方法执行的顺序是不明确的。

@After: 这个注解指定一段代码包含测试卸载操作。在每个测试方法执行后调用这段代码。你可以定义多个@After操作的代码。使用这个注解来释放内存中的资源。

@Test: 使用这个注解标识一个测试方法。 一个单独的测试类可以对应多个测试方法。

@Rule: @Rule通过复用的方法,可以允许你可以灵活的添加和修改每个测试方法。 在Android测试中, 此注解需要和Android测试支持库中提供的测试规则类配合命用。比如 ActivityTestRule和 ServiceTestRule

@BeforeClass: 使用此注解来指定一个测试类的静态方法只能调用一次。这种测试步骤对于耗时操作非常有用, 例如连接数据库操作。

@AfterClass: 使用这个注解来指定一个静态方法, 当类中所有的测试方法都已经运行完成的时候调用。 这个步骤对释放@BeforeClass块中占用的资源非常有用。

@Test(timeout=): 一些注解支持在注解中设置变量值。 例如, 你可以指定一个测试的超时时间,如果一个测试开始并且没有在指定的超时时间内完成, 它自动认为校验失败。超时时间的单位是毫秒, 如 @Test(timeout=5000)。

@Ignore:让Junit忽略某些测试方法,可能是由于测试方法没有完全编写完成或者太过于耗时。

@Test(expected = NullPointerException.class):验证测试方法会抛出某些异常,在Junit测试中通过设置expected参数指定异常类型例如NullPointerException空指针异常,如果该测试方法抛出IllegalArgumentException异常则绿色passed,如果没有抛出的话,则测试红色failed失败。

示例代码:

获取三个数中最大的那个数:这个为了说明setup的操作,没有把max方法写成static类型。

public class MathUtil {
   public int max(int a, int b, int c){
       if(a > b){
           if(a > c){
               return a;
           }else{
               return c;
           }
        }else{
           if(b > c){
               return b;
           }else{
               return c;
           }
        }
    }
}

测试代码

测试代码简单分析:

@Before 注解的setup方法可以让测试程序处理一些初始化操作,比如公有的对象初始化比如下面的代码创建了mathUtil对象。,如果这个对象不单单是在一个测试方法用的对象话,这样可以避免在每个测试类中都编写创建该对象的逻辑。在运行测试代码的时候,首先会执行被@Before注解的方法,注意:被@Before注解的方法,不是执行一次,而是每个被@Test注解的方法执行之前都是调用setup方法。

@After注解的方法,主要用于释放资源,一般很少用到,比如文件关闭,数据库断开链接之类的。和@Before一样,每个测试方法执行完以后,也都会调用@After方法。

验证单元测试的结果,junit本身提供了一整套断言功能,但是目前推荐使用Truth库,下面用的就是Truth库中的比较两个int是否相等的逻辑。断言的逻辑比较简单,更多的API可以参考Truth库

public class MathUtilTest {
        MathUtil mathUtil;
    @Before 
    public void setup() { 
        mathUtil = new MathUtil();
    }
    @Test
    public void testMax() {
           Truth.assertThat(mathUtil.max(1, 2, 3)).isEqualTo(3);
    }
    @After
    fun releaseResource(){
        
    }
}

测试结果

参考:https://blog.csdn.net/u011060103/article/details/107297512

总结

本文主要介绍junit的常见api和Truth断言库的简单使用,整体来看junit是比较简单的,可以针对一些public方法方法做单元测试并验证单元测试的结果是否符合预期。但是我们在实际业务开发的时候往往没有这么简单,主要涉及到以下几个问题:

(1)类中存在大量的private方法,在实际业务开发中,public方法往往只是对外暴露没有实际逻辑,实际逻辑都写在private中,而junit不能直接测试private方法。

(2)对于没有返回值的方法,junit无法断言,这个时候我们有需要测试该void方法是否得到执行。

(3)如果有的方法依赖于Android环境,比如content等。

解决以上的问题,需要借助于Robolectric 或模拟框架(如Mockito库)来实现上述问题。

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

推荐阅读更多精彩内容