MetovaTestKit是一组用于简化iOS应用程序测试编写负担的有用测试助手。
要求
- Swift 4.0
- iOS 9+
安装
MetovaTestKit可通过CocoaPods获取。
MetovaTestKit旨在与单元测试目标一起使用。要安装它,将MetovaTestKit添加到您的项目的Podfile中
target 'YourApp' do
# Your app's pods:
pod 'DataManager'
pod 'ThunderCats'
pod 'MetovaBase'
target 'YourAppTests' do
inherit! :search_paths
pod 'MetovaTestKit'
end
end
然后运行pod install
如果您想测试MetovaTestKit的beta版本,您可以安装最新的develop版本
pod 'MetovaTestKit', :git => 'https://github.com/metova/MetovaTestKit.git', :branch => 'develop'
使用方法
MTKTestable
MetovaTestKit 定义了 MTKTestable
协议。该协议的正确定义可以实现功能性单元测试。它通过将设置和清理代码抽象为你要测试的类型扩展来实现这一点,并允许进行功能性单元测试。
func testOutlets() {
HomeViewControllerClass.test { testVC in
XCTAssertNotNil(testVC.userameTextField)
XCTAssertNotNil(testVC.passwordTextField)
XCTAssertNotNil(testVC.loginButton)
}
}
test
函数会重新抛出在 testBlock
内部抛出的任何错误,这样你可以方便地通过抛出测试用例来表示失败。
func testLogin() throws {
try HomeViewControllerClass.test { testVC in
try testVC.login(username: "jimmythecorgi", password: "woofwoof123")
}
}
测试 UIKit 组件
UIAlertController
验证显示的 alert 是否具有特定的样式、标题、消息和操作。
MTKAssertAlertIsPresented(
by: testVC,
style: .alert,
title: "Warning",
message: "Are you sure you want to delete this user?",
actions: [
ExpectedAlertAction(title: "Delete", style: .destructive),
ExpectedAlertAction(title: "Cancel", style: .cancel)
]
)
UIBarButtonItem
验证 bar button item 是否具有预期的目标/操作对,并且目标确实响应将发送给它的事件。
MTKAssertBarButtonItem(testVC.editBarButtonItem, sends: #selector(MyViewController.didTapEditButton(_:)), to: testVC)
UIControl
您可以用一个断言来验证您的控件动作是否连接,以及目标是否响应将发送事件的选择器。
MTKAssertControl(testVC.loginButton, sends: #selector(LoginViewController.didTapLoginButton(_:)), to: testVC, for: .touchUpInside, "The login button should be hooked up to the login action.")
UICollectionViewCell
断言集合视图对于给定的索引路径返回特定类型的单元格。如果单元格存在,传递一个代码块进行额外的测试。
MTKTestCell(in: tableView, at: indexPath, as: MyCollectionViewCell.self) { testCell in
XCTAssertEqual(testCell.label.text, "Hello World!")
}
参阅 测试示例,了解此方法可以生成测试失败的示例。
UITableViewCell
断言一个表格视图对一个特定的索引路径返回特定类型的单元。
MTKTestCell(in: tableView, at: indexPath, as: MyTableViewCell.self) { testCell in
XCTAssertEqual(testCell.label.text, "Hello World!")
}
参见 测试,了解此方法可以生成的测试失败示例。
UISegmentedControl
验证UISegmentedControl
具有您期望的分段标题。
MTKAssertSegmentedControl(segmentedControl, hasSegmentTitles: ["Followers", "Following"])
测试日期
您可以使用MetovaTestKit断言两个日期在仅考虑指定的组件时相等。
MTKAssertEqualDates(date1, date2, comparing: .year, .month, .day)
此断言接受组件作为可变参数或作为Set<Calendar.Component>
。
let components: Set<Calendar.Component> = [.year, .month, .day, .hour, .minute, .second]
MTKAssertEqualDates(date1, date2, comparing: components)
MTKAssertEqualDates(date3, date4, comparing: components)
MTKAssertEqualDates(date5, date6, comparing: components)
测试自动布局约束
您可以使用MetovaTestKit断言您没有损坏自动布局约束。
MTKAssertNoBrokenConstraints {
// code that does anything that impacts the user interface
// including simply loading a view for the first time
}
如果存在损坏的约束,此断言将失败,并报告测试期间损坏的约束数量。您还可以传递自定义消息。
MTKAssertNoBrokenConstraints(message: "Constraints were broken.") {
// code to test
}
此测试还返回一个值,带有损坏的约束计数。
let brokenConstraintCount = MTKAssertNoBrokenConstraints {
// code to test
}
测试异常
您可以使用MetovaTestKit断言不应该抛出异常的代码没有抛出。在没有MetovaTestKit的情况下,这将导致整个测试套件崩溃。有了MetovaTestKit,这只是一件失败的测试,您仍然可以运行其他测试。
MTKAssertNoException {
// code that should not throw exceptions
// results in passing test if no exceptions are thrown
// results in failing test if exceptions are thrown
}
您还可以传递一条消息来在失败时打印。
MTKAssertNoException(message: "Exception was thrown.") {
// code that should not throw exceptions
// results in passing test if no exceptions are thrown
// results in failing test if exceptions are thrown
}
您还可以测试代码来验证是否抛出异常,并且可以在不使测试套件崩溃的情况下进行此操作。如果您对具体的异常不感兴趣,只想验证代码块是否抛出异常,您可以使用 MTKAssertException
MTKAssertException {
// code that should throw exceptions
// results in passing test if an exception is thrown
// results in a failing test if this closure returns without throwing
}
与 MTKAssertNoException
类似,此函数也接受一条消息
MTKAssertException(message: "No exception was thrown.") {
// code that should throw exceptions
// results in passing test if an exception is thrown
// results in a failing test if this closure returns without throwing
}
这些方法确实在您需要更多有关异常的信息时返回抛出的异常。
guard let exception = MTKAssertException(testBlock: throwingBlock) else {
XCTFail("Block failed to throw an exception")
return
}
// More assertion about the given exception that was returned
if let exception = MTKAssertNoException(testBlock: blockThatShouldntThrow) {
XCTFail("Block should not have thrown but instead threw \(exception)")
return
}
如果闭包没有抛出异常,函数返回 nil
。否则,它返回一个 NSException
实例,您可以验证您的代码块是否抛出了预期的异常。
异步测试
XCTest 使用 expectation(description:)
和 waitForExpectations(timeout:handler:)
提供异步测试功能。然而,当测试简单的延迟异步操作时,这种方法可能会很繁琐,意图可能并不立即明显。使用 MetovaTestKit 的 MTKWaitThenContinueTest(after:)
工具方法,这些类型的测试变得简单,而且读起来很自然。
mockUserSearchNetworkRequest(withResponseTime: 0.5)
testViewController.didTapSearchButton()
XCTAssertFalse(testViewController.searchButton.isEnabled, "The search button should be disabled while a search request is taking place.")
MTKWaitThenContinueTest(after: 1)
XCTAssertTrue(testViewController.searchButton.isEnabled, "Once the request is complete, the search button should be re-enabled.")
文档
文档可在此处找到 http://metova.github.io/MetovaTestKit/.
致谢
MetovaTestKit 由 Metova Inc. 拥有和维护。
如果您想为 MetovaTestKit 贡献,请参阅我们的 贡献指南。
MetovaTestKit 标题图像和其他资产由 Christi Johnson 提供。
许可
MetovaTestKit 在 MIT 许可下可用。有关更多信息,请参阅 LICENSE 文件。