我想编写一些自定义测试断言类型,并以Xcode显示它们,类似于显示XCTAssert()故障的方式:
我是否有办法挂接到Xcode并实现这一目标?
我希望我自己的断言函数在此处以相同的方式内联显示其错误:
到目前为止,我找到的最好的资源是Apple的XCTest source code,但我无法理解它是否甚至包括负责显示错误UI的逻辑。
答案 0 :(得分:2)
最简单的方法是从您的自定义断言中调用XCTFail()
,但传递呼叫站点的文件名和行号。例如:
func verify(myThing: MyThing, file: StaticString = #file, line: UInt = #line) {
// Do your verification. Then when you want to fail the test,
XCTFail("Some message about \(myThing)", file: file, line: line)
}
在呼叫站点,您将让默认参数提供file
和line
。这样看起来就像:
verify(myThing: thing)
在Swift中,XCTest断言是全局函数。这意味着您的助手也可以是全局函数,并且可以在测试套件之间共享,而不必继承XCTestCase
的子类。
答案 1 :(得分:2)
可以完全按照自己的意愿做,我只是设法做到了,像这样:
recordFailure
在任何测试中(只需继承自标准recordFailure
,只需调用XCTestCase
即可实现所需的功能。
XCTestCase
如果要简化对此函数的调用,可以编写一个包装它的扩展函数。
您还可以将XCTestCase
子类化(如果您要共享某些设置(在setup
中被调用,这可能是个好主意,那么您只需要在这个新的超类中进行测试即可)类)。
class TestCase: XCTestCase {
func forwardFailure(
withDescription description: String = "Something went wrong",
inFile filePath: String = #file,
atLine line: Int = #line,
expected: Bool = false
) {
self.recordFailure(
withDescription: description,
inFile: filePath,
atLine: line,
expected: expected
)
}
}
我不确定如何使用expected: Bool
,它是recordFailure
method (source)的必需参数,但看起来Apple大多将其设置为false
。
现在,您可以像下面这样声明您的自定义断言方法(或作为XCTestCase
的扩展,具体取决于您的选择):
extension TestCase {
/// Since `Foobar.Type` does not conform to `Equatable`, even if `Foobar` conforms to `Equatable`, we are unable to write `XCTAssertEquals(type(of: foo), Foobar.self)`, this assert method fixes that.
func XCTAssertType<Actual, Expected>(
of actual: Actual,
is expectedType: Expected.Type,
_ filePath: String = #file,
_ line: Int = #line
) {
if let _ = actual as? Expected { return /* success */ }
let actualType = Mirror(reflecting: actual).subjectType
forwardFailure(
withDescription: "Expected '\(actual)' to be of type '\(expectedType)', but was: '\(actualType)'",
inFile: filePath,
atLine: line
)
}
}
现在它报告错误,不在自定义断言中,而是在呼叫站点?。
如果您查看例如,您也可以转发line
并传递给标准断言。 XCTAssertTrue
,它接受一个line参数和一个file
参数。
答案 2 :(得分:1)
有了Xcode 12
,我们可以使用XCTIssue
内联断言
并且不推荐使用现有的recordFailure
。
这是测试的例子
import XCTest
@testable import TestAssertionForward
class TestAssertionForwardTests: XCTestCase {
func testExample() throws {
assert(actual: 10, expected: 20) // asserts in method
assert(actual: 10, expected: 11) // asserts in method
assertInLine(actual: 10, expected: 11) // asserts in line
assertInLine(actual: 10, expected: 11) // asserts in line
}
}
extension TestAssertionForwardTests {
func assert(actual: Int, expected: Int) {
XCTAssertEqual(actual, expected)
}
func assertInLine(actual: Int, expected: Int, filePath: String = #file, lineNumber: Int = #line) {
if actual != expected {
let location = XCTSourceCodeLocation(filePath: filePath, lineNumber: lineNumber)
let context = XCTSourceCodeContext(location: location)
let issue = XCTIssue(type: .assertionFailure,
compactDescription: "\(actual) is not equal to \(expected)",
detailedDescription: nil,
sourceCodeContext: context,
associatedError: nil,
attachments: [])
record(issue)
}
}
}
下面是失败声明的屏幕截图