android 中的单元测试——使用JUnit 做本地java测试

下面介绍一下如何使用 junit框架。JUnit(https://junit.org/junit5/) 是一个很著名的java 单元测试框架。由于是基于针对java 做测试的,所以是没有android 环境的,当然 android 中的一些工具类也是不能使用的,比如TextUtils(android.text.TextUtils)这个类。

http://d.android.com/tools/testing
https://developer.android.com/training/testing/fundamentals

demo 示例介绍

新建项目

android studio新建的 android 项目默认自带 java unitTestandroid 的相关单元测试框架。

如果没有我们可以在项目的gradle文件中刚添加

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

上面三行代码 testImplementation 'junit:junit:4.12’ 是用来添 junit

下面的两个代码是用来添加 runnerespresso 框架。

由于没有 android 环境的类,所以JUnit 比较适合做纯java的基本类方法的单元测试。

首先来看一个 android studio 创建的项目自带的一个单元测试代码,来看看 JUnit 是如何使用的。 在项目中找到ExampleUnitTest这个类,位置在

Project 模式下 模块名称/src/test/java/{项目包路径}/ExampleUnitTest.java

如图所示:

image.png
image.png

在Project 视图或 Android 视图中测试文件的所在位置

ExampleUnitTest.java 这个文件的代码如下:

package cn.com.qianli.demoforunittest;

import org.junit.Test;
import static org.junit.Assert.*;

/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
  @Test public void addition_isCorrect() throws Exception {
    assertEquals(4, 2 + 2);
  }
}

可以看到代码还是比较简单的,要说明的就是 @Test 是junitTest 框架中的 annotation。

我们进入到Junit的代码中看一下

/**
* Asserts that two longs are equal. If they are not, an
* {@link AssertionError} is thrown.
*
* @param expected expected long value.
* @param actual actual long value
*/

static public void assertEquals(long expected, long actual) {
    assertEquals(null, expected, actual);
}

/**
* Asserts that two longs are equal. If they are not, an
* {@link AssertionError} is thrown with the given message.
*
* @param message the identifying message for the {@link AssertionError} (null
* okay)
* @param expected long expected value.
* @param actual long actual value
*/

static public void assertEquals(String message, long expected, long actual) {
    if (expected != actual) {
        failNotEquals(message, Long.valueOf(expected), Long.valueOf(actual));
    }
}

其实,assertEquals方法是 org.junit中 Assert这个类下的一系列重载方法。如下:

image.png

当然 Assert这个类还有其他方法:

image.png

我们在自己编写单元测试代码的时候可以根据情况使用合适的方法做效验。

我们来执行 ExampleUnitTest 看看效果。在文件上右击鼠标,出现下面这样的弹出框。

可以看到3个运行选项。

第一个 :Run ‘ExampleUnitTest’

这个直接运行测试用例,看结果的。

第二个:Debug ‘ExampleUnitTest’

运行这个是可以直接进行debug的,方式和我们debug android代码类似。

第三个:

Run ‘ExampleUnitTest’ with Coverage

https://www.jetbrains.com/help/idea/running-test-with-coverage.html

image.png
image.png

这里我们运行第一个 Run ‘ExampleUnitTest’ 可以看到结果如下。


image.png

顺便说明,如果你在右击的时候是在某一个方法上右击的,那么执行的是只是某一个方法内的测试代码。

如果右击的时候不再任何方法内,那么执行的是这个测试用例文件中所有的测试方法。

image.png

还可以通过界面上的快捷方式来执行测试用例。

1 的小图标点击后是执行 ExampleUnitTest中所有的测试case, 2 则是执行addition_isCorrect 单个方法的用例。

3处双击和2的效果一样,执行的是addition_isCorrect 单个方法的用例。

image.png

写一个自己的测试用例

下面我们用一个具体的真实业务例子说明一下,在真实项目中测试用例的使用情况。

比如,我们需要写一个简单的字符处理。

需要将电话号码或者银行卡号按照 344 的格式显示,比如 13512341234 显示为 135 1234 1234 。银行卡号也显示为每4为一个间隔显示。

我们二话不说写一个方法签名:

public static String toPhoneGapString(){

  return ""

}

没有任何实现,这个时候在方法签名上右击,

image.png
image.png

选择Create New Test…

image.png

出现的对话框勾选需要创建的方法,我们勾选 toPhoneGapString():String

点击Ok

image.png

出现一个对话框让选择目录,我们这个方法是一个基本的java方法,所以我们选择test目录下的这个目录。

就可以看到有一个新的测试用例文件生成:

image.png

写一行简单的测试用例代码,运行试试看。

image.png

我们的实现是空的,这里当然不可能符合预期。这个时候我们需要改进修改我们的方法toPhoneGapString

给方法签名加入参数 String inputStr

具体实现一段代码如下:

public static String toPhoneGapString(String inputStr) {

  if (inputStr == null) {

    return "";

  }

  StringBuilder stringBuilder = new StringBuilder();

  for (int i = 0; i < inputStr.length();i++) {

    stringBuilder.append(inputStr.charAt(i));

    if((i + 1) % 4 == 3 && (i + 1) != inputStr.length()){

      stringBuilder.append(' ');

    }

  }

  return stringBuilder.toString();

}

对我们的单元测试case也做一下修改,这个时候我们再次执行单元测试文件。

image.png

就可以看到舒心的绿色pass了。(话说,绿色为什么会舒心呢?)

我们再加上更多的测试用例,如下:

  1. 电话号码多一位,以 3 4 4 1 的格式输出,也就是输出多一个空格和多出来的数字。

  2. 电话号码少一位,以 3 4 2 的格式输出,

  3. 电话号码中多空格,希望输出正常的分割电话号码

基于这样的case 我们写单元测试代码

assertEquals("135 1234 1234 2", StringUtil.toPhoneGapString("135123412342"));

assertEquals("135 1234 123", StringUtil.toPhoneGapString("1351234123"));

assertEquals("135 1234 1234", StringUtil.toPhoneGapString("135123412 3 4"));

再次执行。

image.png

发现最后一个case 并没有通过。

这个时候就是我们写代码的时候了,修改方法,知道通过这个case位置。

只要我们在测试用例中覆盖了所有的case,并且保证运行通过,那么我们的小方法就是经过测试的。

作为开发人员也就更加胸有成竹,而不是盲目自信,迷之自信了。

你可能感兴趣的:(android 中的单元测试——使用JUnit 做本地java测试)