安卓测试一(基础)

一 简介

1.0介绍

首先,单元测试并不是一个能直接产生回报的工程,它的运行以及覆盖率也不能直接提升代码质量,但其带来的代码控制力能够大幅度降低大规模协同开发的风险。现在的商业App开发都是大型团队协作开发,不断会有新人加入,无论新人是刚入行的应届生还是工作多年,在代码存在一定业务耦合度的时候,修改代码就有一定风险,可能会影响之前比较隐蔽的业务逻辑,或者是丢失曾经的补丁,如果有高覆盖率的单元测试工程,就能很快定位到新增代码对现有项目的影响,与QA验收不同,这种影响是代码级的。
来自Android单元测试研究与实践

测试一般分为这几个阶段:单元测试、集成测试、系统测试和验收测试。

单元测试(Unit Tsting)是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说, 要根据实际情况去判定其具体含义。 在Java和Android里,单元指具体的一个类或方法, 测试前要移除所有的外部依赖。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最基本的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

集成测试也叫组装测试或联合测试。在单元测试的基础上,将所有模块按照设计要求(如根据结构图)组装成为子系统或系统进行集成测试。实践表明,一些模块 虽然能够单独地工作,但并不能保证连接起来也能正常工作。一些局部反映不出来的问题,在全局上很可能会暴露出来。集成测试是在单元测试的基础上,测试将所有的软件单元按照概要设计规格说明的要求组装成模块、子系统或系统的过程中,各部分工作是否达到或实现相应技术指标及要求的活动。也就是说,在集成测试之前,单元测试应该已经完成,集成测试中所使用的对象应该是已经经过单元测试的软件单元。这一点很重要,因为如果不经过单元测试,那么集成测试的效果将会受到很大影响,并且会大幅增加软件单元代码纠错的代价。

本篇将介绍的是安卓单元测试的基础知识

1.1基础

当我们在AS中创建了新项目之后(File -> New -> New Project),打开默认的未经更改的,app模块下的build.gradle,在最下方我们一般进行添加第三方库依赖的dependencies里,默认是这样的(Kotlin语言,Java会有所不同,改了顺序的)

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.core:core-ktx:1.3.0'
    
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

As会默认添加这些依赖,那么都是什么东西呢,从上到下依次是:
1添加libs的所有jar包为依赖
2Kotlin支持
3AppComPat
4约束布局
5 AndroidKtx(很多东西)
6Junit4 //后面三个是和测试相关的
7 测试相关的吧
8Espresso
这些都是默认导入,接着看文件夹
安卓测试一(基础)_第1张图片

一般项目代码写在这里的第一个文件夹,下方的androidTest,test文件夹就是我们写测试代码的地方了
在这里插入图片描述
关于他们的区别
Android Studio 中的典型项目包含两个用于放置测试的目录。请按以下方式组织整理您的测试:

androidTest 目录应包含在真实或虚拟设备上运行的测试。此类测试包括集成测试、端到端测试,以及仅靠 JVM 无法完成应用功能验证的其他测试。
test 目录应包含在本地计算机上运行的测试,如单元测试。
官网(无需梯子)

1.2 依赖

安卓中AS的依赖方式大家应该都很熟悉了,使用第三方库的时候,一般都会用到,举个小栗子,引用ViewPager2

implementation "androidx.viewpager2:viewpager2:1.0.0"

其他的导入还有
implementation: 参与编译,并且会打包到debug/release apk中;
testImplementation: 只参与单元测试编译,不会打包到debug/release apk包中,不需要设备支持;
androidTestImplementation: 只参与UI测试编译,不会打包到debug/release apk包中,需要设备支持.
除此之外,还有provided、apk、debugImplementation和releaseImplentation依赖方式。
provided: 只参与编译,不会打包到debug/release apk中;
apk: 不参与编译,只会打包到debug/release apk中;
debugImplementation: 只参与debug编译,只会打包到debug apk中;
releaseImplementation: 只参与release编译,只会打包到release apk中。
还有一个api导入,这个用的很多,一般在基础模块中使用,比如你有一个基础的库,在这里做一些功能的封装,一般就会用api导入库,这样子你的Phone Module使用这个基础库的时候相当于自己也导入了这些库,应该很好理解吧。

 // 事件总线
    api 'org.greenrobot:eventbus:3.2.0'
    // 网络
    api 'com.squareup.okhttp3:okhttp:3.12.1'

在 Android Gradle Plugin 3.0 时代,Google 使用 implementation 和 api 选项取代过去的 compile 选项。既然接口都变了,Google 索性将其他的配置项也进行了改名,方便大家理解其配置的含义。需要注意的是,老版本的接口没有被立刻删除,但是在下一个主要版本中会被删除。下面是各个配置项的官方中文解释:
安卓测试一(基础)_第2张图片
参考

1.3测试类生命周期回调

在Junit里主要有After、AfterClass、Before、BeforeClass、ClassRule、FixMethodOrder、Ignore、Rule等几个注解。

接下来对常用的几个Junit注解进行讲解:

@Test: 在JUnit 3中是通过对测试类和测试方法的命名来确定是否是测试,并且所有的测试类必须继承JUnit 的测试基类。在JUnit4中定义一个测试方法变得简单很多,只需要在方法前加上@Test就可以了。
@Ignore: 如果想暂时不运行某些测方法或测试类,可以在方法前加上这个注解。
@BeforeClass: 在测试类里的所有用例运行之前,运行一次这个方法,如创建数据库,读取文件,初始化模拟新用户等。
@AferClass: 和BeforeClass对应,在测试类里所有用例运行一次之后执行,用于处理一些测试后续工作,如清理数据,将设置的测试环境恢复为开发环境等收尾工作。这两个注解的方法必须时public static void ,即公开、静态、无返回。
@Before: 与BeforeClass的区别在于,@Before会在每个测试用例前都执行一次,主要用于一些独立于用例之外的准备工作,可以视情况灵活使用,该方法必须public void,不能为static,因为这个方法不止运行一次。
@After: 每个测试用例执行后运行一次。
@RunWith: 指定测试运行器,就是放在测试类名之前的

@RunWith(JUnit4::class)
@LargeTest
class LearnActivityExamTest {

@FixMethodOrder: 指定测试方法的顺序。
一个Junit4的单元测试用例执行顺序如下
@BeforeClass->@Before->@Test->@After->@AfterClass
每一个测试方法的调用顺序如下:
@Before->@Test->@After

1.4 安卓的测试

测试一般分为两类,一个是本地测试,即仅在本地计算机上运行的单元测试。这些测试编译为在Java 虚拟机(JVM)上本地运行,以最大限度地缩短执行时间。如果你的测试依赖于Android框架中的对象,建议使用Robolectric。对于项目中的依赖项的测试,可以使用模拟对象来模拟依赖项的行为,或使用mockito库来模拟依赖项的行为。

另一种测试是仪 器测试,即在Android 设备或模拟器上运行的单元测试。这些测试可以访问检测信息,如被测应用程序的上下文。使用此方法运行具有复杂Android依赖关系的单元测试,这些依赖关系需要更强大的环境,如Robolectric。由于代码中的一些方法通常依赖系统或者其他组件,所以需要在测试时隔离这些方法。可以使用模拟(mock)的对象来模拟依赖的对象。Android API提供了一套可以提供测试使用的模拟类,可以使用mockito库来模拟依赖项行为。通常在setup()方法中创建模拟对象,并在teardown()方法中释放它们。

二关于安卓测试框架

(这里只做简介,后面会对每一个框架做单独的介绍)

1.0 Junit

Junit官网
(来自百度百科)JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。 [1]
JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。
目前安卓测试依赖的就是这个东东。最新出了Junit5了,感兴趣可以去了解

1.1Espresso

Espresso官网
是谷歌在2013年10月推出的开源Android UI测试框架,目前(2020/7/2)最新版本是3.2,当前Android Studio默认集成的就是Espresso测试库。
它有以下特点:
核心 API 小巧、可预测且易于学习,但仍可进行自定义。Espresso 测试会清楚地说明预期、交互和断言,让您不受样板内容、自定义基础架构或杂乱的实现细节干扰。
测试运行速度极快!(个人觉得还好)当它在静止状态下对应用界面进行操纵和断言时,让您无需等待、同步、休眠和轮询。

1.2 Robolectric

Robolectric官网
(以下来自官网翻译)听起来就觉得功能还挺强大的
Robolectric是一个框架,可将快速可靠的单元测试引入Android。测试可以在几秒钟内在您的工作站上的JVM中运行。
与传统的基于仿真器的Android测试不同,Robolectric测试在沙盒中运行,从而允许将Android环境精确配置为每个测试所需的条件,将每个测试与其邻居隔离,并使用测试API扩展Android框架,从而提供控制Android框架的行为和断言状态的可见性。

1.3 Mockio

Mockio的Github
Mock 最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。

1.4UI Automator

UI Automator 官网
UI Automatoe测试多个应用的界面
UI Automator 是一个界面测试框架,适用于整个系统上以及多个已安装应用间的跨应用功能界面测试。
测试框架提供了一组 API,用于构建在用户应用和系统应用上执行交互的界面测试。通过 UI Automator API,您可以执行在测试设备中打开“设置”菜单或应用启动器等操作。UI Automator 测试框架非常适合编写黑盒式自动化测试,此类测试的测试代码不依赖于目标应用的内部实现细节。

你可能感兴趣的:(测试)