ios单元测试_正确进行iOS中的单元测试

ios单元测试

为什么我的应用程序在每次发行后都会变得如此麻烦?

为什么我的质量检查小组经常报告重复性问题和崩溃?

遏制此类问题的最佳解决方案单元测试。 在此博客文章中,我们将看到如何将单元测试有效地合并到我们的代码库中,从而减少重复的测试工作和错误频率。

有3种类型的开发人员级别测试:

  1. 单元测试 (我们今天将重点讨论)
  2. 整合测试
  3. UI测试
单元测试基本上是将较大的复杂逻辑分解为较小的可测试逻辑。

为现有代码库编写单元测试可能是一个巨大的挑战。 这就是为什么我们应该继续开发带有代码的单元测试用例的原因。 因此,理想的开发工作流程应如下所示:

  1. 制作BRD和后端工作流程(您的UML)。
  2. 制作设计文档。
  3. 根据业务逻辑为每个功能/模块编写测试用例。
  4. 通过将较大的逻辑分解为较小的部分,开始为每个功能编写单元测试用例。
  5. 开始构建和完善您的单元测试用例的逻辑基础。

由于我们生活在不理想的世界中,因此我们将不得不为现有代码库编写测试用例。 当使用诸如测试驱动开发,面向协议的编程和依赖注入之类的技术开始新项目时,可以轻松地进行单元测试,而在对现有代码库/项目进行单元测试时,我们必须将这些技术与大量技术结合在一起。代码重构(很多时候,我的意思是很多代码重构)。

XCTest库

XCTest库提供了一个通用框架,用于在Swift中为Swift软件包和应用程序编写单元测试。 我们可以在创建新项目时包括单元测试用例,也可以稍后在我们的项目中添加单元测试目标。 在测试类中提及您的可测试目标(要测试的应用)以访问其类。 单元测试用例的生命周期有2种主要方法

  1. 建立()
  2. 拆除()

这些方法分别在每个测试用例执行之前和之后自动调用。 我们可以使用这些方法执行任何资源分配-解除分配。

注意:测试用例应完全独立,因为它们是异步执行的。

什么啊 为什么? 怎么样? 单元测试用例

什么才算是有效的测试用例? 一个可以同时通过和失败的方法。 大多数时候,我们测试应用程序的核心业务逻辑,该逻辑由以下几部分组成:

  • 数据解析和数据处理:来自API,文件,缓存,DB,本地存储,用户默认值,共享对象,全局变量,常量等的数据。
  • 实用程序/支持类:日期格式化程序,字符串操作逻辑,数据验证检查,无检查等逻辑。
  • 扩展,数据管理器,数据模型,视图模型(特定于特定模块)等类中的逻辑。
  • 包含if-else逻辑,switch,map-reduce-filter逻辑等的方法。

我们需要识别并隔离每个可测试的部分,使其独立于其他代码部分。 例如,一种方法应仅执行一项任务,例如检查输入文本中的有效数字。

怎么样? 既然我们知道必须测试哪些部分,那么让我们看一下如何测试它们。

1.模拟正在使用伪数据或模拟数据测试您的代码逻辑。 用模拟的数据编写单元测试用例几乎可以真实地模拟测试,这使其成为进行单元测试的理想方法。 列出需要模拟的代码段:

  • 共享实例,局部和全局变量,数据模型
  • 文件和其他本地资源
  • 核心数据和其他数据库,例如SQLite
  • Apple API,例如CNContact,钥匙串商店实例,位置等
  • 网络通话
  • 缓存的数据

模拟数据以进行单元测试有时可能会非常麻烦,尤其是网络调用时。 比起代码本身的实际开发,我们可能不得不在模拟数据上付出更多的编码工作。 有时,开发人员必须模拟整个类。 列出两种抑制模拟问题的方法:

  • 依赖注入:它有助于独特地初始化类或对象,以便可以轻松对其进行模拟。 例如,使用数据源作为强制参数来初始化控制器类,或者使用作为参数传递的共享会话来初始化网络呼叫,使模拟变得更加容易。
  • POP(面向协议的编程):它以松散耦合的扩展名和协议的形式帮助抽象类的代码。 扩展方法无法在我们的XCTest类中直接进行测试,我们仅需要通过扩展协议公开特定于扩展的逻辑。部分模拟CNContact的示例用于测试ContactsManager类

某些情况下可以通过部分模拟来测试,而某些情况下需要对要测试的对象进行完全模拟。 如果将这种方法应用于现有代码库,则需要大量代码重构。

2. 存根使用自定义框架/库来存根网络响应,而不实际对服务器进行任何网络调用。 在这里,我们可以完全控制要测试的响应,而无需任何Internet或服务器依赖性。 在编写单元测试用例时,存根需要更少的编码工作。 一些最流行的存根库是用于XCTest(unit)测试的OHHTTPStubsMockingjayHippolyte

可以说,我们将能够通过存根模拟大多数快乐的测试场景。 如果从实际服务器收到的响应有任何添加或更改,我们将必须更新存根。

3. TDD(测试驱动开发)将大大减少开发人员的模拟和存根工作,或者使模拟更容易,因此我们根本不需要对数据进行存根以进行单元测试。 顾名思义,测试驱动的开发以某种方式影响开发方法,使所得的代码更加独特,独立和可测试。

开发人员通过将较大的逻辑分解为较小的部分,开始为每个功能编写单元测试用例,然后继续开发和改进在过程中标识的单元测试用例的逻辑基础。 TDD专注于要测试的逻辑部分的关键,因此隔离了代码的各个可测试部分。 我将尝试在另一篇文章中用一个示例介绍TDD。

注意:当我们要对一段代码进行单元测试时,我们必须检查“ 为什么 ”。 问问自己“这段代码应该在单元测试中进行测试”还是在这种情况下,还有其他测试措施可以使测试自动化吗? 我们无法测试仅返回特定字符串(如字体,颜色,键或常量)的方法。
另外,我们应确保我们不会在类中添加太多代码以使其无法测试,然后编写单元测试用例以测试为测试原始类而添加的额外代码。 我们不想陷入那种螺旋循环。
总是,找到一种方法来编写单元测试用例,同时尽可能减少模拟和数据操作。 专注于逻辑的关键。

面临的挑战

  • 编写现有遗留代码与新代码的测试用例。
  • 使代码可测试,然后进行代码重构(很多代码重构)。
  • 无法访问用于直接模拟的私有变量-使用getter setter方法。
  • 它不能直接测试私有方法。

优点

  • 充当代码文档。 我们将在单元测试用例中很好地分离大多数业务逻辑测试用例。
  • 大大降低了错误发生率。 是的,从个人经验来看,确实如此。
  • 它使我们可以编写更好的代码。
  • 重构现有代码时很有用。 当我们重构或进行代码升级时,破解它的机会很高。 测试用例将立即为我们指出错误的方向,我们可以在错误进行质量检查之前将其修复。
  • 应用行为也可以(在一定程度上)进行测试。
  • 降低了循环复杂性,使代码更简单,更健壮。 理想的圈复杂度应在4–7(良好至中等范围)之间。

如果您想了解更多关于圈复杂度的信息,请观看   这个 。 它很好地解释了这种令人费解的术语。

骗局

  • 必须对代码进行大量重写和重构,以使其可测试。

代码覆盖率

理想的代码覆盖率应为80%-100%。 Xcode具有用于单元测试的供应检查类明智代码覆盖范围。

开发流程

下面的图片描述了将单元测试集成到代码库中时,典型管道的外观。 我们既可以在提交代码之前手动运行单元测试用例,也可以在CICD管道中使用脚本自动运行单元测试用例,或者两者都做(推荐)。

这更多是一篇有关单元测试的翔实文章。 下一篇文章将更加面向编码,包括依赖项注入,存根和POP。

如果您有任何反馈意见或希望添加您认为有用的内容,请随时发表评论。

希望您喜欢阅读本文。 谢谢!

翻译自: https://hackernoon.com/approaching-unit-testing-in-ios-correctly-lmr3u13

ios单元测试

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值