Android测试系列之二 - 构建本地单元测试

来源:互联网 发布:java中jsonobject遍历 编辑:程序博客网 时间:2024/05/18 20:36


Android测试系列之一 - 测试分类(节选)

Android测试系列之二 - 构建本地单元测试

Android测试系列之三 - 构建仪器单元测试



建议在阅读此篇文章之前,请先阅读测试分类,以便对Android 测试有个大致性的认识,现在,言归正传,回到如何构建

本地单元测试的问题上


如果你的单元测试没有依赖项或者仅仅有一些简单的Android依赖项,那么你应该在本地开发机上去运行你的测试。

这种测试的方式是非常高效的,因为它避免了去加载你的app和测试代码到真机或者模拟器上的开销。相应地,这种

单元测试所消耗的时间将会大大地减小。在这种方式下,你通常需要使用一个模拟的framework, 例如 Mockito,

去充当这种依赖关系。


搭建测试环境

Android Studio的工程下,你需要将本地单元的测试文件放在 module-name/src/test/java/目录下,在你创建
一个新的工程的时候,这个目录就已经创建好了。

为了使你的工程能够使用 JUnit 4 framework提供的标准API,你需要配置一下这个测试的依赖项。如果你的测试需要与
Android 依赖项进行一个交互,需要包含 Mockito 库以便简化本地单元测试。如果想要了解更多关于在本地单元测试
中如何使用mock对象的问题,可以参考 Mocking Android dependencies

在你app的build.gradle文件中,你需要指定这些库作为一种依赖:
dependencies {    // Required -- JUnit 4 framework    testCompile 'junit:junit:4.12'    // Optional -- Mockito framework    testCompile 'org.mockito:mockito-core:1.10.19'}


创建一个本地测试单元类

你的本地单元测试类应该写成一个JUnit 4的测试类。 JUnit 在java领域中,是一种最受欢迎和使用最广的单元测试
框架。这个框架的最新的版本是 JUnit 4 ,它比之前的版本更清晰易懂,更加灵活。对于JUnit 4,你不用再去继承 junit.
framework.TestCase这个类,你也不用在你测试方法名前面添加一个“test”的前缀,也不用再去使用junit.framework 
or junit.extensions包下的类。

为了创建一个基本的JUnit 4测试类,你需要创建一个java类,然后让这个java类包含一个或多个测试方法。测试方法是以
@Test注解的方式开头,然后里边包含你想要执行的或者校验的功能。

下面这个示例展示了如何实现一个本地单元测试类。示例中的这个测试方法emailValidator_CorrectEmailSimple_ReturnsTrue
就是用来校验isValidEmail() 是否 返回正确的结果。

import org.junit.Test;import java.util.regex.Pattern;import static org.junit.Assert.assertFalse;import static org.junit.Assert.assertTrue;public class EmailValidatorTest {    @Test    public void emailValidator_CorrectEmailSimple_ReturnsTrue() {        assertThat(EmailValidator.isValidEmail("name@email.com"), is(true));    }    ...}
为了测试你app的组件是否返回期待的结果,你可以使用  junit.Assert 方法去比较组件的状态是否和某些期待的
结果一致。为了让这个测试更具有可读性,你可以使用 Hamcrest matchers (比如:is()和equalTo()方法)去比较
返回的结果和期待的结果。


模拟Android依赖项

默认情况下, Android Plug-in for Gradle 是在一个修改过的android.jar库的基础上去运行你的本地单元测试的。
这个android.jar库实际上是不包含任何代码的。换言之,在本地单元测试中调用Android 类中的方法就会抛出异常。这
是为了确保在你的测试代码中没有去使用Android平台相关的东西。

为了能方便地地测试那些与依赖项相关联的组件,在代码中,你可以使用一个模拟的框架去解决这个外部依赖项的问题。
通过使用一个模拟对象去替代Android 依赖项,这样你就可以把你的单元测试与Android 系统的其他部分予以分开。针对
java平台而开发Mockito 这个模拟框架兼容Android单元测试。有了它,当被调用之时,你就可以让这个模拟对象返回
某些特定的值。

在使用这个框架的时候,为了能够添加一个模拟对象到你的本地单元测试中,需要遵循以下步骤:

1>在build.gradle文件包含Mockito库这个依赖项,具体参考 Set Up Your Testing Environment

2>在单元测试类定义的开头部分,添加 @RunWith(MockitoJUnitRunner.class)注释。这个注释是为了判断Mockito
这个框架是否被正确地使用以及简化了模拟对象初始化的工作。

3>因Android 依赖项去创建一个模拟对象,需要在这个属性声明之前添加一个 @Mock 的注释。

4>为了判断依赖项的状态,你可以通过通过使用when()然后thenReturn()的方法去指定一个条件,在某个条件满足之时,就让其返回某个值。

下面这个例子展示了如何使用一个模拟的Context对象去创建一个单元测试:

import static org.hamcrest.MatcherAssert.assertThat;import static org.hamcrest.CoreMatchers.*;import static org.mockito.Mockito.*;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.Mock;import org.mockito.runners.MockitoJUnitRunner;import android.content.SharedPreferences;@RunWith(MockitoJUnitRunner.class)public class UnitTestSample {    private static final String FAKE_STRING = "HELLO WORLD";    @Mock    Context mMockContext;    @Test    public void readStringFromContext_LocalizedString() {        // Given a mocked Context injected into the object under test...        when(mMockContext.getString(R.string.hello_word))                .thenReturn(FAKE_STRING);        ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);        // ...when the string is returned from the object under test...        String result = myObjectUnderTest.getHelloWorldString();        // ...then the result should be the expected one.        assertThat(result, is(FAKE_STRING));    }}
为了了解更多关于Mockito框架,可以参考 Mockito API reference 和sample code中的SharedPreferencesHelperTest类。




运行本地单元测试

运行本地单元测试,请遵循以下步骤:

1>
确保你的工程文件已通过 按钮 Sycn Project 进行了更新操作

2>
用其中一种方式去运行你的测试文件:
I>
运行单个测试,可以打开Project窗体,然后右键单击这个测试文件,然后点击 Run
II>
运行一个类中的所有方法,可以在测试文件中右键单击类或者方法,然后点击Run
III>
运行目录下所有的测试文件,右键单击这个目录,然后选择 Run tests



参考:
《Building Local Unit Tests》



0 0