Android单元测试

235 阅读3分钟

    什么是单元测试呢?单元测试就是针对最小的功能单元编写测试代码。Java程序最小的功能单元是方法,因此,对Java程序进行单元测试就是针对单个Java方法的测试。

    单元测试有什么好处呢?在学习单元测试前,我们可以先了解一下TDD,既测试驱动开发。所谓测试驱动开发,是指先编写接口,紧接着编写测试。编写完测试后,我们才开始真正编写实现代码。在编写实现代码的过程中,一边写,一边测,什么时候测试全部通过了,那就表示编写的实现完成了。当然,这是一种理想情况。大部分情况是我们已经编写了实现代码,需要对已有的代码进行测试。

    对于AndroidSDK来说,单元测试覆盖除了核心的功能方法之外,还要包括对外的接口。

一、单元测试覆盖率量化标准

1、行覆盖率

2、判断覆盖率

3、条件覆盖率

4、路径覆盖率

二、工具选择:JUnit+PowerMockit

    JUnit只能mock方法,不能mock实例;并且JUnit使用本地JVM提供运行环境,如果测试的单元依赖了Android框架(或者测试类依赖于其他外部类的情况),比如用到了Android中的Context、SP类的一些方法,本地JVM将无法提供这样的环境,所以我们一般会结合其他开源库共同完成单元测试。

    Android(Java)常用的单元测试开源库一般是Mockito模拟框架,Mockito可以Mock对象,同时可以模拟安卓的运行环境,以及一些service访问返回等。但是,Mokito只能模拟public的方法(网上有通过反射修改private方法access来实现mock方法的,感觉比较麻烦)比较适用于大多标准的单元测试case。

    PowerMockito与Mockito的用处总体上一样,都是为了mock外部的、不容易构造的环境,但是PowerMokito可以用于解决更多复杂的情况,PowerMockito可以对private/final/static的方法进行mock,同时也可以兼容Mockito。

三、常用方法

四、单元测试示例
五、IDEA(AndroidStudio)配置及使用
六、覆盖率检测及报告生成
七、其他(随笔)

@EnabledOnOs(OS.WINDOWS)  // 只在Windows系统是才跑的test
@DisabledOnOs(OS.WINDOWS) // 不在Windows系统上跑的test
@DisabledOnJre(JRE.JAVA_8) // 只能在Java9或更高版本上跑的test
@EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*") // 只能在64位操作系统上跑的test
@EnabledIfEnvironmentVariable(named = "DEBUG", matches = "true") // Debug = true时跑的test

参数化测试:

@ParameterizedTest
@MethodSource
void testCapitalize(String input, String result) {
    assertEquals(result, StringUtils.capitalize(input));
}

static List<Arguments> testCapitalize() {
    return List.of( // arguments:
            Arguments.arguments("abc", "Abc"), //
            Arguments.arguments("APPLE", "Apple"), //
            Arguments.arguments("gooD", "Good"));
}

@MethodSource注解在被测试方法上,默认对应同名静态方法进行测试。

另一种传入测试参数的方法是使用@CsvSource,它的每一个字符串表示一行,一行包含的若干参数用,分隔,因此,上述测试又可以改写如下:

@ParameterizedTest
@CsvSource({ "abc, Abc", "APPLE, Apple", "gooD, Good" })
void testCapitalize(String input, String result) {
    assertEquals(result, StringUtils.capitalize(input));
}

如果有成百上千的测试输入,那么,直接写@CsvSource就很不方便。这个时候,我们可以把测试数据提到一个独立的CSV文件中,然后标注上@CsvFileSource

@ParameterizedTest
@CsvFileSource(resources = { "/test-capitalize.csv" })
void testCapitalizeUsingCsvFile(String input, String result) {
    assertEquals(result, StringUtils.capitalize(input));
}

JUnit只在classpath中查找指定的CSV文件,因此,test-capitalize.csv这个文件要放到test目录下,内容如下:

apple, Apple
HELLO, Hello
JUnit, Junit
reSource, Resource

参考:

www.liaoxuefeng.com/wiki/125259…

www.jianshu.com/p/aa51a3e00…

www.jianshu.com/p/51930cc5d…

blog.csdn.net/q1519599065…