构建 Instrumented 单元测试
Instremented 单元测试是运行在物理设备或者模拟器上的测试,他们可以利用 Android 框架的 API 和支持的 API ,例如 Android 测试支持库。如果你的测试需要获取设备信息(例如目标应用的 Context )或者他们需要一个Android框架组件的实现(例如一个 Parcelable 或者一个 SharedPreferences 对象)。
使用 Instrumented 单元测试也有助于减少编写维护模拟对象代码的工作量,当然如果你选择的话,你仍然可以使用模拟框架来模拟任何依赖关系。
设置您的测试环境
在你的 Android Studio 项目中,你必须将本地单元测试的源文件存储在 module-name/src/androidTest/java/ 目录下,当你创建一个新的工程时这个文件夹已经存在并且包含了一个 instrumented 测试的例子。
在开始之前,你应该 下载Android测试支持库设置 ,他提供了让你更快速的为你的应用构建运行 instrumented 测试的API。测试支持库包括了一个 JUnit4 测试运行器 AndroidUnitRunner 和用于功能性 UI 测试的 API( Espresso 和 UI Automator )。
你还需要为你的项目配置 Android 测试依赖,已使用测试支持库提供的测试运行器和规则 API 。为了简化您的测试开发,你也应该包含 Hamcrest库 ,他可以让你创建更灵活的断言( assertions )。
在你的app级的 build.gradle 文件中,你需要将这些库指定为依赖:
dependencies {
androidTestCompile 'com.android.support:support-annotations:24.0.0'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
// Optional -- Hamcrest library
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
// Optional -- UI testing with Espresso
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
// Optional -- UI testing with UI Automator
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
}
注意: 如果你的构建配置包含 support-annotations 库的 compile 依赖 和 espresso-core 库的 androidTestCompile 依赖,那么由于依赖冲突,你的构建可能会失败。为了解决这个问题,按照下面的方式更新您的 espresso-core 的依赖。
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' })
为了使用 JUnit4 测试类,请确保您的应用的app 级别的 build.gradle 文件中包含了下面的设置,将 AndroidJUnitRunner 指定为项目默认的测试工具运行器。
android {
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
创建一个 Instrumented 单元测试类
你的 instrumented 单元测试类应该被写成一个 JUnit4 测试类。要了解更多关于创建 JUnit4 测试类和使用 JUnit断言和注解,请看 创建一个本地测试类。
要创建一个 instrumented JUnit4 测试类,请在测试类定义的开头加上 @RunWith(AndroidJUnit4.class) 注解。你也需要确认 Android测试支持库提供的 AndroidJUnitRunner 类作为您默认的测试运行器。
下面的代码展示了你应该如何去编写一个 instrumented 单元测试类来测试 LogHistory 类的 Parcelable 接口是否被正确的实现了:
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
import android.util.Pair;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LogHistoryAndroidUnitTest {
public static final String TEST_STRING = "This is a string";
public static final long TEST_LONG = 12345678L;
private LogHistory mLogHistory;
@Before
public void createLogHistory() {
mLogHistory = new LogHistory();
}
@Test
public void logHistory_ParcelableWriteRead() {
// Set up the Parcelable object to send and receive.
mLogHistory.addEntry(TEST_STRING, TEST_LONG);
// Write the data.
Parcel parcel = Parcel.obtain();
mLogHistory.writeToParcel(parcel, mLogHistory.describeContents());
// After you're done with writing, you need to reset the parcel for reading.
parcel.setDataPosition(0);
// Read the data.
LogHistory createdFromParcel = LogHistory.CREATOR.createFromParcel(parcel);
List<Pair<String, Long>> createdFromParcelData = createdFromParcel.getData();
// Verify that the received data is correct.
assertThat(createdFromParcelData.size(), is(1));
assertThat(createdFromParcelData.get(0).first, is(TEST_STRING));
assertThat(createdFromParcelData.get(0).second, is(TEST_LONG));
}
}
创建测试套件
为了组织你的 instrumented 单元测试的运行,你可以将一组测试类分到一个测试套件类中,并将这些测试一起运行。测试套件可以嵌套,你的测试套件可以组合其他测试套件并且所有的组件测试类一起运行。
测试套件包含在测试包中,类似于主应用程序包,按照惯例,测试套件包通常 .suite 后缀结尾。(例如, com.example.android.testing.mysample.suite)。
腰围你的单元测试类创建测试套件,请 import JUnit RunWith 和 Suite 类。在你的测试套件中,添加 @RunWith(Suite.class) 和 @Suite.SuitClasses() 注解。在 @Suite.SuiteClasses() 注解中,列出每个测试类或者测试套件作为参数。
下面的例子展示了你应该如何实现一个名为 UnitTestSuite 的测试套件。给测试条件将CalculatorInstrumentationTest 和 CalculatorAddParameterizedTest 测试类分组在并一起运行。
import com.example.android.testing.mysample.CalculatorAddParameterizedTest;
import com.example.android.testing.mysample.CalculatorInstrumentationTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
// Runs all unit tests.
@RunWith(Suite.class)
@Suite.SuiteClasses({CalculatorInstrumentationTest.class,
CalculatorAddParameterizedTest.class})
public class UnitTestSuite {}
运行 Instrumented 单元测试
想要运行你的 instrumented 测试,请按照下面步骤执行:
通过点击工具栏的 Sync Project, 确保你的项目的Gradle是同步的。
以下面方式之一运行测试:
要运行一个简单的测试,请打开 Project 窗口,然后右键单击一个测试,并点击 Run 选项。
要测试一个类中的所有方法,请右键点击一个类或者测试文件中的一个方法然后点击 Run 选项。
要运行一个文件夹中所有的测试,请右键点击这个文件夹,并选择 Run tests 选项。
Android Gradle 插件编译 instrumented 单元测试代码位于默认的文件夹(src/androidTest/java/),构建一个测试 APK 和一个 生产 APK ,在连接的设备或者模拟器上同时安装这两个 APK ,然后运行这些测试。Android Studio 将会在 Run 窗口显示 instrumented 测试的执行结果。
在 Firebase 测试实验室运行你的测试
使用 Firebase 测试实验室 ,你可以在很多流行的 Android 设备和设备配置(区域,屏幕方向,屏幕大小,平台版本)上同时运行你的测试。这些测试运行在 Google 远程数据中心的物理和虚拟设备上。你可以直接从 Android Studio 上 或者使用命令行部署你的应用到测试实验室上。测试结果提供测试日志,并包含任何应用错误的详细信息。
配置测试矩阵并运行测试
Android Studio 提供了集成的工具,允许您配置您希望如何将您的测试部署到 Firebase 测试实验室。在使用 Blaze plan billing 创建了一个 Firebase 工程后,你可以创建一个测试配置并运行你的测试:
点击主菜单上的 Run > Edit Configuration
点击 Add New Configuration + 并选择 Android Tests。
在这个 Android Test configuration 对话框中:
a. 输入或者选择你的测试的详细信息,例如测试名字,module 类型,和测试类。
b. 从 Deployment Target Options 的下拉菜单中选择 Firebase Test Lab Device Matrix .
c. 如果您尚未登录,请点击 Connect to Google Cloud Platform ,并允许 Android Studio 连接到您的账户.
d. 在 Cloud Project 旁边,点击 按钮并从列表中选择你的 Firebase 项目。
创建并配置测试矩阵:
a. 在 Matrix Configuration 下拉列表旁边,点击 Open Dialog .
b. 点击 Add New Configuration(+).
c. 在 Name 区域,为你的新的配置输入一个名字。
d. 选择你想要测试程序的设备,Android版本,所在区域和屏幕方向。在生成测试结果时,Firebase 测试实验室将根据您的选择组合测试您的应用。
e. 点击 OK 保存您的配置。
点击 Run/Debug Configurations 对话框中的 OK 以退出。
点击 Run 运行您的测试。
图1. 为 Firebase 测试实验室创建一个测试配置
分析测试结果
当 Firebase 测试实验室完成运行您的测试后,Run 窗口将会打开显示结果,像图2所示那样。您可能需要点击 Show Passed 来查看您所有已执行的测试。
图2. 查看使用 Firebase 测试实验室的 instrumented 测试结果
你也可以按照 Run 窗口测试执行日志开始处显示的链接,在网络上分析您的测试。
要了解更多的关于测试结果的分析,请看 分析 Firebase Android 测试实验室的结果