今天为大家准备两版(Android+iOS)的单元测试

内容强大

收起来慢慢看~

一、Android 单元测试

Android 项目默认会创建两个测试目录,分别为 src/test 和 src/androidTest 前者是单元测试目录,后者是依赖 Android 框架的 instrumentation 测试目录。

声明测试也有区别,前者是 testImplementation 后者是androidTestImplementation,我们今天讨论的是前者,也叫 Local Unit Test,意思也就是说不依赖 Android 真机或者模拟器,可以直接在本地 JVM 上运行的单元测试。

Android 的单元测试与普通的 java 项目并没有太大差异,首先需要关注的是如何分辨那些类或者方法需要测试。

一个好的单元测试的一个重要特性就是运行速度要快,通常是毫秒级的,而依赖 Android 框架的代码都需要在模拟器上或者真机上运行(也不是绝对的),速度不可避免的会慢很多,所以我们在做 Android 单元测试的时候会避免让被测试代码对 Android 框架有任何依赖。

在这个条件下,一般适合进行单元测试的代码就是:

MVP 结构中的 Presenter 或者 MVVM 结构中的 ViewModel

Helper 或者 Utils 工具类

公共基础模块,比如网络库、数据库等

如果你的项目中代码与 Android 框架耦合比较高,那么可能就不得不先对目标代码进行重构,然后再编写测试代码。如何重构不在本文讨论范围,请自行探索。

如何判断测试的有效性

测试代码很快写完了,你可能会想,怎么才能衡量测试的有效性呢?这里就要引入另外一个概念,叫测试覆盖率。

测试覆盖率有着不同的维度,比如类数量、方法数量、行数、条件分支等等,具体什么意思不在本文讨论范围,大家可以自行探索。Android Studio 内置了工具可以帮我们进行统计。

Android Studio 会帮我们创建一个 Task,而在运行按钮右边,还有一个按钮叫 “Run [test-task-name] with coverage”,这个就是 IDE 内置的统计测试覆盖率的工具啦。

运行之后会自动打开一个 Coverage 结果页面窗口,点进去就可看到当前测试 task 对相关的被测试代码的一个覆盖情况。

点击打开具体类还能看到每一行代码有没有执行到,非常好用,为我们对测试用例的调整和完善提供了很好的参考价值。

二、iOS单元测试

iOS 开发(或者 MacOS、tvOS、watchOS 等)中,单元测试有多种方式,主要分为 Xcode 提供的以及第三方测试框架这两类:

Xcode自带XCTest:XCTest 是 Xcode自带的单元测试工具,其前身是 OCUnit,随着 Xcode 的发展,XCTest 已经越来越完善,功能也越强大。

第三方框架GHUnit:GHUnit 是 GitHub 上著名的开源测试框架,可视化、开源、扩展等功能,让其相比 XCTest 更加强大(现在的 XCTest 也很完善了,不过 GHUnit 比较老,现在已经停止维护,不建议使用)

OCMock:OCMock 也是 Github 上的著名开源测试框架,用于 Mock、Stub,为测试提供数据作假功能。

以上三种就是比较主流的测试 Xcode 单元测试途径,还有一些 BDD 行为测试框架:

什么是 BDD?

BDD,即行为驱动开发,是敏捷开发技术之一,通过自然语言定义系统行为,以功能使用者的角度,编写需求场景,且这些行为描述可以直接形成需求文档,同时也是测试标准。

Specta:GitHub 上轻量级的 BDD 测试框架。

Expecta:与 Specta 同个作者,是一个功能强大的匹配框架。

Kiwi:Kiwi 是重量级的,集 OCMock、Specta、Expecta 所拥有的功能与一身的 BDD DSL 测试框架。

其他的,还有一些其他测试工具、测试方式,如:

Nocilla:强大的 HTTP 模拟测试工具。

OHHTTPStubs:也是 HTTP 模拟测试工具。

TUDelorean:基于 Objective-C 的时间模拟测试工具。

KIF:集成/界面测试工具,其它的还有 Frank、Calabash 等。

GitHub + Jenkins + TestFlight:自动化测试。

Monkey Test:随机测试。




android 提交检查 eslint androidtestimplementation_单元测试


而其中,关于XCTest 测试你需要知道:

1、创建测试类

注意,所有测试类都继承自 XCTestCase。

2、测试类的结构

默认创建的单元测试类为一个 .m 文件,里面包含了以下四个方法:

- (void)setUp:在每个测试用例开始前调用,可以做一些测试准备工作,为可选方法。

- (void)tearDown:在每个测试用例结束后调用,可以做一些测试收尾工作,为可选方法。

- (void)testExample:默认创建的测试用例。

- (void)testPerformanceExample:性能测试方法。

3、测试流程

当我们默认执行测试时,系统找到所有的测试类,并执行每个测试方法;我们也可以选择性地执行某些测试而已,比如,在 scheme 中 disable 某个用例,或者直接在测试导航栏中每个测试用例后面的运行按钮,单独执行某个测试。

默认流程如下:

上一个测试类 -> 当前类+ (void)setUp -> [ - (void)setUp -> 测试方法 -> - (void)tearDown ] (循环直至当前类测试方法全部执行完) -> 当前类 + (void)tearDown -> 下一个测试类

关于Specta、Expecta 测试你需要知道

Specta 和 Expecta 都是出自 Github 作者 Orta 之手,他最出名的开源框架莫过于 Cocoapods。

Specta

Specta 是一个轻量级 BBD 测试框架,其为 DSL (Domain-Specific Language) 模式,让测试更加接近于自然语言描述,更加易懂。

1、主要有以下特点

容易集成到项目中。

基于XCTest编写,可以很好地与XCTest配合使用。

2、语法介绍

SpecBegin 声明了一个测试类,SpecEnd 结束类声明

describe (context) 块声明了一组实例

it (example/specify) 是一个单一的样例

beforeAll 是一个执行于全部同级块之前的块,仅仅执行一次。afterAll 与beforeAll相反,是在全部同级块之后执行的块。仅仅执行一次。

beforeEach/afterEach,在每一个同级块执行的时候,都会执行一次,而beforeAll/afterAll仅仅会执行一次

it/waitUntil/done()。异步调用,注意完毕异步操作之后。必须调用done()函数。

Expecta

Expecta 是基于 Objective-C/Cocoa 的断言框架,XCTest 自带的断言 XCAssert 有好几个基础操作,不过基础的断言不太丰富,和 Specta 也没有很适配。Expecta 不一样,将匹配过程从断言中剥离开,可以很好地适配 Specta 的 DSL 断言块。

Expecta 有以下几个特点:

没有类型限制,比如数值 1,并不用关心它是整形还是浮点数

链式编程,可读性高,如:expect(foo).notTo.equal(1)

反向匹配,断言不匹配只需加上 .notTo 或者 .toNot,如:expect(x).notTo.equal(y)

延时匹配,可以在链式表达式中加入 .will、.willNot、.after(interval) 等操作来延时匹配可扩展,支持增加自定义匹配。