OCHamcrest
OCHamcrest 是一个 Objective-C 模块,它提供以下功能
- 一组“匹配器”对象库,用于声明规则以检查给定的对象是否满足这些规则。
- 一个框架,用于编写您自己的匹配器。
匹配器可以组合起来创建灵活的测试意图表达式。它们也可以用于其他目的,例如用户输入验证。
内容
我的第一个 OCHamcrest 测试
我们将从一个非常简单的 Xcode 单元测试开始,但将使用 OCHamcrest 的 assertThat
构造和一些预定义的匹配器,而不是使用 XCTest 的 XCTestAssertEqualObjects
函数。
@import OCHamcrest;
@import XCTest;
@interface BiscuitTest : XCTestCase
@end
@implementation BiscuitTest
- (void)testEquals
{
Biscuit* theBiscuit = [[Biscuit alloc] initWithName:@"Ginger"];
Biscuit* myBiscuit = [[Biscuit alloc] initWithName:@"Ginger"];
assertThat(theBiscuit, equalTo(myBiscuit));
}
@end
《assertThat》函数是一个用于测试断言的样式化句子。在本例中,断言的主题是对象 theBiscuit
,它是第一个方法参数。第二个方法参数是用于 Biscuit
对象的匹配器,这里是一个使用 -isEqual:
方法检查一个对象是否等于另一个对象的匹配器。由于 Biscuit
类定义了 -isEqual:
方法,所以测试通过。
OCHamcrest 的函数实际上是使用 "HC_" 包前缀(如 HC_assertThat
和 HC_equalTo
)声明的,以避免名称冲突。为了使测试编写更快,测试代码更易读,默认情况下提供了可选的简短语法。例如,用 HC_assertThat
代替 assertThat
。
预设匹配器
OCHamcrest 附带了一个有用的匹配器库
对象
conformsTo
- 匹配符合协议的对象equalTo
- 匹配相等对象hasDescription
- 匹配对象的-description
hasProperty
- 匹配具有给定名称的方法的返回值instanceOf
- 匹配对象类型isA
- 精确匹配对象类型,没有子类nilValue
、notNilValue
- 匹配nil
,或不匹配nil
sameInstance
- 匹配相同对象throwsException
- 匹配抛出异常的块- HCArgumentCaptor - 匹配任何内容,捕获所有值
数字
closeTo
- 匹配接近给定值的数字greaterThan
、greaterThanOrEqualTo
、lessThan
、lessThanOrEqualTo
- 匹配数值顺序isFalse
- 匹配零isTrue
- 匹配非零
文本
containsSubstring
- 匹配字符串的一部分endsWith
- 匹配字符串的结尾equalToIgnoringCase
- 匹配整个字符串但忽略大小写equalToIgnoringWhitespace
- 匹配完整字符串,但忽略多余的空白startsWith
- 匹配字符串的开始部分stringContainsInOrder
,stringContainsInOrderIn
- 匹配字符串的部分,保持相对顺序
逻辑
allOf
,allOfIn
- 将所有匹配器“与”在一起anyOf
,anyOfIn
- 将所有匹配器“或”在一起anything
- 匹配任何内容(在组合匹配器中不需要关注特定值时很有用)isNot
- 取消匹配器的匹配
集合
contains
,containsIn
- 完整匹配整个集合containsInAnyOrder
,containsInAnyOrderIn
- 匹配整个集合,但顺序可以不同containsInRelativeOrder
,containsInRelativeOrderIn
- 匹配包含相对顺序项的集合everyItem
- 匹配如果集合中的每个项目都满足给定的匹配器hasCount
- 将元素数量与另一个匹配器进行比较hasCountOf
- 匹配具有给定元素数量的集合hasEntries
- 匹配包含键值对的字典hasEntriesIn
- 匹配列表中的键值对的字典hasEntry
- 匹配包含键值对的字典hasItem
- 匹配如果给定的项出现在集合中hasItems
,hasItemsIn
- 匹配如果所有给定的项以任何顺序出现在集合中hasKey
- 匹配具有键的字典hasValue
- 匹配具有值的字典isEmpty
- 匹配空集合isIn
- 匹配对象位于给定集合中onlyContains
,onlyContainsIn
- 如果集合的项出现在给定的列表中则匹配
装饰器
describedAs
- 为匹配器提供一个自定义的失败描述is
- 提高可读性的装饰器 - 请参阅下方的“语法糖”
许多这些匹配器的参数不仅可以接受匹配值,还可以接受另一个匹配器,因此匹配器可以组合起来以提高灵活性。例如,only_contains(endsWith(@"."))
将匹配任何项都以句点结尾的集合。
语法糖
OCHamcrest 努力使你的测试尽可能可读。例如,is
匹配器是一个包装器,它不为底层匹配器添加任何额外行为。以下断言都是等效的
assertThat(theBiscuit, equalTo(myBiscuit));
assertThat(theBiscuit, is(equalTo(myBiscuit)));
assertThat(theBiscuit, is(myBiscuit));
最后一种形式是允许的,因为 is
使用 equalTo
包装了非匹配器参数。其他匹配器(它们接受匹配器作为参数)提供了类似的快捷方式,将非匹配器参数包装在 equalTo
中。
常见问题
如何断言异步调用?
assertWithTimeout
会在匹配器满足或达到超时时间前持续评估一个表达式。例如,
assertWithTimeout(5, thatEventually(self.someString), is(@"expected"));
这将在超时后5秒内重复检查字符串是否等于“expected”。thatEventually
是一个便利宏,用于创建代码块。
我是否可以添加自定义匹配器?
OCHamcrest 带有许多有用的匹配器,但你可能会发现,有时你需要创建自己的匹配器来满足测试需求。有关更多信息,请参阅“编写自定义匹配器”指南。
关于Swift?
如何将 OCHamcrest 添加到我的项目中?
示例文件夹展示了通过 Swift Package Manager、CocoaPods 或预构建框架准备好使用 OCHamcrest 的项目。
Swift 包管理器
在 Package.swift 清单的 dependencies 数组中包含 OCHamcrest 包。
dependencies: [
.package(
url: "https://github.com/hamcrest/OCHamcrest",
.upToNextMajor(from: "9.0.0")
),
],
然后将 OCHamcrest 添加到 .testTarget 的依赖中。
.testTarget(
name: "ExampleTests",
dependencies: [
"Example",
"OCHamcrest",
]
),
CocoaPods
如果您想使用 Cocoapods 添加 OCHamcrest,请在 Podfile 中添加以下依赖项。大多数人会希望在测试目标中使用 OCHamcrest,而不是将 Any pods 包含在主要目标中
target 'MyTests' do
inherit! :search_paths
use_frameworks!
pod 'OCHamcrest', '~> 9.0'
end
Carthage
在 Cartfile 中添加以下内容
github "hamcrest/OCHamcrest" ~> 9.0
然后将构建出的框架从适当的 Carthage/Build 目录拖到项目中,但请禁用“将项目复制到目标组的文件夹中”选项。
预构建框架
在 GitHub 上可以找到预构建的二进制文件。这个二进制文件作为 OCHamcrest.xcframework,包含以下架构
- macOS
- Mac Catalyst
- iOS 设备
- iOS 模拟器
- tvOS 设备
- tvOS 模拟器
- watchOS 设备
- watchOS 模拟器
将XCFramework拖到您的项目中。
构建自己的
如果您想自己构建OCHamcrest,先克隆仓库,然后
$ cd Source
$ ./MakeDistribution.sh