建立本地单元测试

官方原文 Building Local Unit Tests

如果你的单元测试没有依赖或者只有Android上的简单依赖,你应该在本地开发机器上运行测试。 这种测试方法是高效的,因为它可以帮助您避免每次运行测试时将目标应用程序和单元测试代码加载到物理设备或模拟器上的开销。 因此,运行单元测试的执行时间大大减少。 使用这种方法,通常使用模拟框架(如Mockito)来实现任何依赖关系。

设置测试环境


在您的Android Studio项目中,必须将用于本地单元测试的源文件存储在module-name/src/test/java/。 创建新项目时,此目录已存在。

您还需要为项目配置测试依赖关系,以使用JUnit 4框架提供的标准API。 如果您的测试需要与Android依赖关系交互,请包括Mockito库以简化本地单元测试。 要了解有关在本地单元测试中使用模拟对象的更多信息,请参阅模拟Android依赖

在应用程序的顶级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 3的Android单元测试的方法不同,使用JUnit 4,您不需要扩展 junit.framework.TestCase 类。您也不需要在测试方法名称前加上’test’关键字,或者使用 junit.frameworkjunit.extensions 包中的任何类。

要创建基本的JUnit 4测试类,请创建一个包含一个或多个测试方法的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));
    }
    ...
}
package com.le.bbs;

import com.le.bbs.api.RequestInterceptor;

import org.junit.Assert;
import org.junit.Test;

/**
 * To work on unit tests, switch the Test Artifact in the Build Variants view.
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        String query = "sso_tk=&appKey=lemeapp&timeStamp=1471516952";
        Assert.assertEquals(RequestInterceptor.generateSign(query), "35083f2dbece");
    }
}

验证通过 Process finished with exit code 0
验证不通过

org.junit.ComparisonFailure: 
Expected :35083f2dbece
Actual   :35083f2dbece3

要测试应用程序中的组件是否返回预期结果,请使用junit.Assert方法执行验证检查(或断言),以便将受测试组件的状态与某些预期值进行比较。 为了使测试更可读,可以使用Hamcrest matchers(例如is() 和equalTo() 方法)将返回的结果与预期结果进行匹配。

模拟Android依赖

默认情况下,Android的插件Gradle针对android.jar库的修改版本执行您的本地单元测试,该版本不包含任何实际代码。 相反,从单元测试中调用Android类的方法会抛出异常。 这是为了确保只测试你的代码,不依赖于Android平台的任何特定的行为(你没有明确的模拟)。

您可以使用模拟框架在代码中消除外部依赖关系,以便轻松测试您的组件是否达到预期。 通过用模拟对象替换Android依赖项,您可以将单元测试与Android系统的其余部分隔离,同时验证这些依赖关系中的方法是否被正确调用。 Java的Mockito 模拟框架(1.9.5及更高版本)提供了与Android单元测试的兼容性。 使用Mockito,您可以配置模拟对象以便在调用时返回一些特定值。

要使用此框架需要将模拟对象添加到本地单元测试,请遵循以下编程模型:

  1. 在build.gradle文件中包含Mockito库依赖关系,如文章上面的设置测试环境所述。
  2. 在单元测试类定义的开始,添加@RunWith(MockitoJUnitRunner.class)注释。 这个注释告诉Mockito测试运行器验证框架使用的正确性,并简化了你的模拟对象的初始化。
  3. 要为Android依赖项创建模拟对象,请在字段声明之前添加@Mock注释。
  4. 要消除依赖关系的行为,可以使用when()和thenReturn()方法指定条件并返回值。

以下示例显示如何创建使用mock上下文对象的单元测试。

package com.le.bbs;

import android.content.Context;

import com.le.bbs.test.ClassUnderTest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;

/**
 * @author Sayangnala
 * @ClassName: UnitTestSample
 * @Description: 单元测试样例(来源于官方文档)
 * @date 2016/10/13 10:09
 */
@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...
        //org.mockito.Mockito.when
        when(mMockContext.getString(R.string.app_name)).thenReturn(FAKE_STRING);

        ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
        String result = myObjectUnderTest.getHelloWorldString();

        //..then the result should be the expected one.
        //org.hamcrest.MatcherAssert.assertThat
        //org.hamcrest.CoreMatchers.is
        assertThat(result, is(FAKE_STRING));
    }
}

要测试的类:ClassUnderTest.java

package com.le.bbs.test;

import android.content.Context;

import com.le.bbs.R;

/**
 * @author yuhushuan
 * @ClassName: ClassUnderTest
 * @Description: 配合单元测试类
 * @date 2016/10/13 10:32
 */
public class ClassUnderTest {
    Context mContext;

    public ClassUnderTest(Context context) {
        mContext = context;
    }

    public String getHelloWorldString() {
        return mContext.getString(R.string.app_name);
    }
}

要了解有关使用Mockito框架的更多信息,请参阅示例代码中的Mockito API参考和sample code 的SharedPreferencesHelperTest类。

如果测试代码抛出Android.jar中Android API的异常,您可以通过项目的顶级build.gradle文件中添加以下配置来替换返回null或0:

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }
}

警告:将returnDefaultValues属性设置为true应该小心。 零/零返回值可以在测试中引入回归,这难以调试,并且可能允许失败的测试通过。 只能使用它作为最后的手段。

运行本地单元测试


按照下列步骤运行本地单元测试:
1. 通过单击工具栏中的同步项目,确保您的项目与Gradle同步。
2. 使用以下方法之一运行测试:

  • 要运行单个测试,请打开“Project”窗口,然后右键单击测试,然后单击Run 。
  • 要测试类中的所有方法,请右键单击测试文件中的类或方法,然后单击Run 。
  • 要在目录中运行所有测试,请右键单击目录并选择 Run tests。

Gradle的Android插件编译位于默认目录(src/test/java/)中的本地单元测试代码,构建一个测试应用程序,并使用默认的测试运行器类在本地执行它。 然后,Android Studio将在“运行”窗口中显示结果。

### 如何在本地环境配置并执行Web应用程序的单元测试 #### 准备工作 为了能够在本地环境中顺利地配置和执行Web应用程序的单元测试,首先要确保已经正确安装了所需的软件包以及工具。对于基于Python编写的Web应用而言,通常会采用Django作为框架来构建站点[^1]。 #### 安装必要的库和支持模块 如果尚未完成,则需先按照官方文档指导完成Django及其依赖项的安装过程。接着要引入支持编写与运行自动化试的相关扩展,比如`django-nose`或内置于Django内的试客户端等。 #### 编写试案例 针对想要检验的功能逻辑,在对应的app目录下创建名为tests.py的新文件,并在此处定义具体的TestCase类继承自unittest.TestCase或是更推荐使用的django.test.TestCase。下面给出一段简的例子用于展示如何实现这一点: ```python from django.urls import reverse from django.test import TestCase, Client class SimpleTest(TestCase): def setUp(self): self.client = Client() def test_details(self): response = self.client.get(reverse('index')) self.assertEqual(response.status_code, 200) ``` 这段代码展示了怎样利用Django自带的试客户端发起HTTP请求并对返回的状态码做基本校验。 #### 执行试命令 一切准备就绪之后,可以通过终端进入项目根路径位置输入如下指令启动全部已注册的应用程序下的试集合: ```bash python manage.py test ``` 此操作将会自动发现所有符合条件(即位于apps内部且命名为tests.py)的脚本并将它们依次加载到内存里去逐一调用其中的方法体来进行验证活动;与此同时还会输出详细的日志信息帮助开发者定位潜在的问题所在之处。 #### 生产环境注意事项 值得注意的是,在实际部署至线上之前除了上述提到的内容外还需要考虑更多方面的事情,例如但不限于调整settings.py里的某些参数选项以适应不同的硬件条件限制或者是增强安全防护措施防止恶意入侵行为的发生等等[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值