Swift单元测试Quick+Nimble

文章目录

    • 使用Quick+Nimble
      • 1、苹果官方测试框架XCTest的优缺点
      • 2、选择Quick+Nimble的原因:
      • 3、Quick+Nimble使用介绍
        • 集成:
        • Quick关键字说明:
        • Nimble中的匹配函数
          • 等值判断:使用equal函数
          • 是否是同一个对象:使用beIdenticalTo函数
          • 比较:
          • 比较浮点数
          • 类型检查
          • 是否为真
          • 是否有异常
          • 集合关系
          • 字符串
          • 检查集合中的所有元素是否符合条件
          • 检查集合个数
          • 匹配任意一种检查
      • 4、Quick使用总结

使用Quick+Nimble

github地址

1、苹果官方测试框架XCTest的优缺点

优点:与 Xcode 深度集成,有专门的Test 导航栏。

缺点:
1)因为受限于官方测试API,因此功能不是很丰富。
2)在书写性和可读性上都不太好。在测试用例太多的时候,由于各个测试方法是割裂的,想在某个很长的测试文件中找到特定的某个测试并搞明白这个测试是在做什么并不是很容易的事情。
3)所有的测试都是由断言完成的,而很多时候断言的意义并不是特别的明确,对于项目交付或者新的开发人员加入时,往往要花上很大成本来进行理解或者转换。另外,每一个测试的描述都被写在断言之后,夹杂在代码之中,难以寻找。
4)使用XCTest测试另外一个问题是难以进行mock或者stub

2、选择Quick+Nimble的原因:

主要是由于苹果官方框架的测试方法及断言不明确,可读性不好,难以分辨,交接项目需要花费的时间很多,所以建议采用三方测试框架
目前主流的三方测试框架主要有:
oc中:kiwi 、specta、cedar
swift:quick+nimble、Sleipnir
由于项目是使用的swift语言,所以主要采用quick+nimble,用于单元测试和断言。
如果你的项目是OC的,推荐使用kiwi,目前是start最多的三方框架。

3、Quick+Nimble使用介绍

Quick 是一个建立在XCTest 上,为Swift 和Objective-C 设计的测试框架. 对测试使用Swift编写的App非常友好,对Swift使用者来说,Quick是最佳选择
它通过DSL 去编写非常类似于RSpec 的测试用例。
Nimble 就像是Quick 的搭档,它提供了匹配器作为断言,用于编写匹配模式。

集成:

使用pod集成方便快捷:

pod ‘Quick’
pod ‘Nimble’

新建一个测试类,继承于QuickSpec父类,然后重写spec( )方法
示例代码:

finalfinal class BindDeviceTests: QuickSpec {

    override func spec() {
        //所有测试放在这里
        
        describe("test BindDeviceDB") {
            let findMac = "34:94:54:C2:E3:C6"
            let bindedMacs = ["34:94:54:C2:E3:C6",
                              "D8:0B:CB:62:08:5F",
                              "FF:F2:00:08:21:9C"]
            
            it("test saveBindDevice") {
                let bindDevice = BindDevice()
                bindDevice.scaleName = "test"
                bindDevice.userId = testLoginUserId
                bindDevice.mac = testMac
                expect(bindDevice.save()).to(beTrue())
            }
            
            it("test findBindDeviceList") {
                let list = BindDevice.findBindDeviceList()
                printLog(message: "test findBindDeviceWithMac: \(String(describing: list?.count))")
                expect(list?.count) == 6
            }
			
            ......
			
            xit("test findNotUploadBindDevices") {
                let list = BindDevice.findNotUploadBindDevices()
                printLog(message: "test findNotUploadBindDevices: \(String(describing: list?.count))")
                expect(list).to(beNil())
            }

        }
    }

}
Quick关键字说明:

在这里插入图片描述

Nimble中的匹配函数
等值判断:使用equal函数
  • expect(actual).to(equal(expected))
  • expect(actual) == expected
  • expect(actual) != expected
是否是同一个对象:使用beIdenticalTo函数
  • expect(actual).to(beIdenticalTo(expected))
  • expect(actual) === expected
  • expect(actual) !== expected
比较:
  • expect(actual).to(beLessThan(expected))
  • expect(actual) < expected
  • expect(actual).to(beLessThanOrEqualTo(expected))
  • expect(actual) <= expected
  • expect(actual).to(beGreaterThan(expected))
  • expect(actual) > expected
  • expect(actual).to(beGreaterThanOrEqualTo(expected))
  • expect(actual) >= expected
比较浮点数
  • expect(10.01).to(beCloseTo(10, within: 0.1))
类型检查
  • expect(instance).to(beAnInstanceOf(aClass))
  • expect(instance).to(beAKindOf(aClass))
是否为真
  • expect(actual).to(beTruthy())
  • expect(actual).to(beTrue())
  • expect(actual).to(beFalsy())
  • expect(actual).to(beFalse())
  • expect(actual).to(beNil())
是否有异常
  • // Passes if actual, when evaluated, raises an exception:
  • expect(actual).to(raiseException())
  • // Passes if actual raises an exception with the given name:
  • expect(actual).to(raiseException(named: name))
  • // Passes if actual raises an exception with the given name and reason:
  • expect(actual).to(raiseException(named: name, reason: reason))
  • // Passes if actual raises an exception and it passes expectations in the block
  • // (in this case, if name begins with ‘a r’)
  • expect { exception.raise() }.to(raiseException { (exception: NSException) in
    • expect(exception.name).to(beginWith(“a r”))
  • })
集合关系
  • // Passes if all of the expected values are members of actual:
  • expect(actual).to(contain(expected…))
  • expect([“whale”, “dolphin”, “starfish”]).to(contain(“dolphin”, “starfish”))
  • // Passes if actual is an empty collection (it contains no elements):
  • expect(actual).to(beEmpty())
字符串
  • // Passes if actual contains substring expected:
  • expect(actual).to(contain(expected))
  • // Passes if actual begins with substring:
  • expect(actual).to(beginWith(expected))
  • // Passes if actual ends with substring:
  • expect(actual).to(endWith(expected))
  • // Passes if actual is an empty string, “”:
  • expect(actual).to(beEmpty())
  • // Passes if actual matches the regular expression defined in expected:
  • expect(actual).to(match(expected))
检查集合中的所有元素是否符合条件
  • // with a custom function:
  • expect([1,2,3,4]).to(allPass({$0 < 5}))
  • // with another matcher:
  • expect([1,2,3,4]).to(allPass(beLessThan(5)))
检查集合个数
  • expect(actual).to(haveCount(expected))
匹配任意一种检查
  • // passes if actual is either less than 10 or greater than 20
  • expect(actual).to(satisfyAnyOf(beLessThan(10), beGreaterThan(20)))
  • // can include any number of matchers – the following will pass
  • expect(6).to(satisfyAnyOf(equal(2), equal(3), equal(4), equal(5), equal(6), equal(7)))
  • // in Swift you also have the option to use the || operator to achieve a similar function
  • expect(82).to(beLessThan(50) || beGreaterThan(80))

4、Quick使用总结

  • 使用Quick,编写it方法执行多个test方法,实际执行顺序,按照字母排序执行,可以从控制台打印得出
  • 单元测试的方法,保存、删除、修改等会对数据库真正意义上的修改
  • 使用xit,表示不测试这些方法
  • 当既有it又有fit,表示只会测试fit的方法( 只要存在f开头的方法,单元测试开始执行便只会执行f开头的方法,即使不在同一个测试类中
  • 当使用describe、context、it嵌套使用时,当最外层方法使用了x开头的,整个入口都不会进入测试,即使嵌套里面使用了f开头的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/306396.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鼠标随动指定区域高亮显示(Excel聚光灯)

实例需求&#xff1a;工作表中数据表实现跟随鼠标选中高亮效果&#xff0c;需要注意如下几个细节需求 数据表为连续区域&#xff0c;但是不一定从A1单元格开始数据表的前两行&#xff08;标题行&#xff09;不使用高亮效果数据表中已经应用了条件格式&#xff0c;高亮显示取消…

stm32的FMC数据访问与突发模式

数据访问 配置外部存储器的宽度为 16 位&#xff0c; FMC 将使用内部的 ADDR[25:1]地址来作为对外部存储器的寻址地址 FMC_A[24:0]&#xff0c;这段描述是在解释在STM32的FMC&#xff08;Flexible Memory Controller&#xff09;中&#xff0c;如何配置外部存储器的宽度为16位…

YOLOv5改进 | 2023主干篇 | EfficientViT替换Backbone(高效的视觉变换网络)

一、本文介绍 本文给大家带来的改进机制是EfficientViT(高效的视觉变换网络),EfficientViT的核心是一种轻量级的多尺度线性注意力模块,能够在只使用硬件高效操作的情况下实现全局感受野和多尺度学习。本文带来是2023年的最新版本的EfficientViT网络结构,论文题目是Effici…

麒麟操作系统缓存rpm包,制作离线yum源

缓存rpm包&#xff0c;以make为例 mkdir -p /data/yum yumdownloader --resolve --destdir/data/yum make制作离线yum包 yum install createrepo -y cd /data/yum createrepo .写yum配置文件/etc/yum.repos.d/local.repo [local-repo] namelocal-repo baseurlfile:///data/…

spring boot 自动扫描Controller、Service、Component原理

项目里面为什么不加上ComponentScan("com.yym.*")注解&#xff0c;也能加载到子目录里面的Controller&#xff0c;Service&#xff0c;Component的bean呢&#xff1f; 启动类没有ComponentScan注解 SpringBootApplication public class BootStrap {public static v…

2023.11.16

1. 数据预处理&#xff0c; 对于质量守恒&#xff0c;加和比都为100% 数据清洗 箱型图 散点图 3σ 进行一次正态性检验 描述性分析&#xff1a;计算平均值、标准差。趋势分析&#xff0c;通过散点图&#xff0c;折线图&#xff0c;观察不同混合比对焦油、水、合成气体的…

数据挖掘在制造业中的预测与优化应用

随着大数据时代的到来&#xff0c;数据挖掘技术在各行各业的应用日益广泛&#xff0c;尤其在制造业中&#xff0c;其对于提升生产效率、降低运营成本、优化供应链管理等方面发挥着不可替代的作用。本文将探讨数据挖掘在制造业中的预测与优化应用&#xff0c;通过深入剖析实际案…

linux(ubuntu)中drontab定时器命令详解

linux&#xff08;ubuntu&#xff09;中drontab定时器命令详解 crontab 是一个用于创建、编辑和管理用户的定时任务的命令&#xff0c;它可以让用户在指定的时间自动执行指定的命令或脚本。 基本语法 -e&#xff1a;编辑用户的 crontab 文件&#xff1b;-l&#xff1a;列出用…

sentinel熔断简单实现

sentinel详细介绍网址 基于qps限流 package mainimport ("fmt"sentinel "github.com/alibaba/sentinel-golang/api""github.com/alibaba/sentinel-golang/core/base""github.com/alibaba/sentinel-golang/core/flow""log"…

CentOS常用命令

CentOS常用命令 1 背景知识1.1 Centos 简介1.2 centos 和ubuntu的区别1.3 安装centos的时候需要注意什么 2 常用命令集锦2.1 文件目录类&#xff1a;2.2 驱动挂载类&#xff1a;2.3 关机命令&#xff1a;2.4 查看系统信息命令&#xff1a;2.5 文本命令2.6 系统管理命令&#xf…

Redis异步写失败后补数逻辑设计

背景 最近各种机房事故频发&#xff0c;所以很多公司都对Redis存储等进行异步多活&#xff0c;我们公司采用的方式是通过客户端双写的方式来实现异地Redis机房的备份&#xff0c;但是当异地机房出现临时网络故障时&#xff0c;就涉及到了如何进行补数的操作&#xff0c;本文就…

6 - 数据备份与恢复|innobackupex

数据备份与恢复&#xff5c;innobackupex 数据备份与恢复数据备份相关概念物理备份与恢复逻辑备份&#xff08;推荐&#xff09;使用binlog日志文件实现对数据的时时备份‘使用日志 恢复数据 innobackupex 对数据做备份和恢复增量备份与恢复 数据备份与恢复 数据备份相关概念 …

【算法Hot100系列】搜索插入位置

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

资源调度(2)-----pod的亲和性和反亲和性

集群调度: schedule的调度算法。 预算策略&#xff1a;过滤出合适的节点 优先策略&#xff1a; 选择部署的节点 nodeName:硬匹配&#xff0c;不走调度策略。node01. nodeSelector&#xff1a;根据节点的标签选择&#xff0c;会走调度算法。 只要是走调度算法&#xff0c;在不满…

软件测试|Python对JSON的解析和创建详解

简介 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;已经成为当今互联网应用中广泛使用的数据格式之一。Python提供了内置的模块来解析和创建JSON数据&#xff0c;使得在Python中处理JSON变得非常简单。本文将详细介绍Python…

ProtoBuf一些踩坑记录

一、Protobuf学习基础 学习的资料很多也很全&#xff0c;这里添加几个链接进行Protobuf的基础学习的链接&#xff0c;链接中的案例使用C编辑&#xff1a; 链接&#xff1a;Protobuf介绍及简单使用(上&#xff09;_google_protobuf_version-CSDN博客 Protobuf介绍及简单使用(下&…

从网页连接socket服务器和I/O

1.i/o InputStream和InputStreamReader是Java I/O类库中的两个关键类&#xff0c;用于处理字节流。它们的主要区别在于它们处理数据的方式。 InputStream: InputStream是用于读取字节流的抽象类。它是所有字节输入流类的父类。InputStream的子类可以从不同的数据源读取字节&…

了解 Node.js 的运行机制:从事件循环到模块系统(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

typora导出html添加目录

typora导出html添加目录 使用方法 首先要从typora导出html文件&#xff0c;之后用记事本编辑器html文件 找到文档最后面&#xff0c;如图&#xff1a; 用文字编辑类工具打开sideBar.txt&#xff0c;复制其中所有内容【内容在下面】 在如上图的位置插入所复制的内容 打开修改…

面试宝典进阶之Java线程面试题

T1、【初级】线程和进程有什么区别&#xff1f; &#xff08;1&#xff09;线程是CPU调度的最小单位&#xff0c;进程是计算分配资源的最小单位。 &#xff08;2&#xff09;一个进程至少要有一个线程。 &#xff08;3&#xff09;进程之间的内存是隔离的&#xff0c;而同一个…