gpt4 book ai didi

unit-testing - 在 Swift 中测试断言

转载 作者:IT王子 更新时间:2023-10-29 05:10:18 25 4
gpt4 key购买 nike

我正在为具有断言的方法编写单元测试。 Swift 语言指南建议对“无效条件”使用断言:

Assertions cause your app to terminate and are not a substitute for designing your code in such a way that invalid conditions are unlikely to arise. Nonetheless, in situations where invalid conditions are possible, an assertion is an effective way to ensure that such conditions are highlighted and noticed during development, before your app is published.

我要测试失败案例。

但是,Swift 中没有 XCTAssertThrows(从 Beta 6 开始)。我如何编写单元测试来测试断言是否失败?

编辑

根据@RobNapier 的建议,我尝试将 XCTAssertThrows 包装在 Objective-C 方法中并从 Swift 调用此方法。这不起作用,因为宏没有捕获由 assert 引起的 fatal error ,因此测试崩溃。

最佳答案

assert 及其兄弟 precondition 不抛出异常不能被“捕获”(即使使用 Swift 2 的错误处理)。

您可以使用的一个技巧是编写您自己的替代品,它可以做同样的事情,但可以被替代以进行测试。 (如果您担心性能,只需 #ifdef 将它用于发布版本。)

自定义前置条件

/// Our custom drop-in replacement `precondition`.
///
/// This will call Swift's `precondition` by default (and terminate the program).
/// But it can be changed at runtime to be tested instead of terminating.
func precondition(@autoclosure condition: () -> Bool, @autoclosure _ message: () -> String = "", file: StaticString = __FILE__, line: UWord = __LINE__) {
preconditionClosure(condition(), message(), file, line)
}

/// The actual function called by our custom `precondition`.
var preconditionClosure: (Bool, String, StaticString, UWord) -> () = defaultPreconditionClosure
let defaultPreconditionClosure = {Swift.precondition($0, $1, file: $2, line: $3)}

测试助手

import XCTest

extension XCTestCase {
func expectingPreconditionFailure(expectedMessage: String, @noescape block: () -> ()) {

let expectation = expectationWithDescription("failing precondition")

// Overwrite `precondition` with something that doesn't terminate but verifies it happened.
preconditionClosure = {
(condition, message, file, line) in
if !condition {
expectation.fulfill()
XCTAssertEqual(message, expectedMessage, "precondition message didn't match", file: file.stringValue, line: line)
}
}

// Call code.
block();

// Verify precondition "failed".
waitForExpectationsWithTimeout(0.0, handler: nil)

// Reset precondition.
preconditionClosure = defaultPreconditionClosure
}
}

例子

func doSomething() {
precondition(false, "just not true")
}

class TestCase: XCTestCase {
func testExpectPreconditionFailure() {
expectingPreconditionFailure("just not true") {
doSomething();
}
}
}

( gist )

当然,类似的代码也适用于 assert。但是,由于您正在测试行为,您显然希望它成为接口(interface)契约的一部分。您不希望优化代码违反它,assert 将被优化掉。所以最好在这里使用 precondition

关于unit-testing - 在 Swift 中测试断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25529625/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com