Swift -在Xcode中内联显示Assert失败,就像XCTest失败一样?

2ul0zpep  于 2023-08-02  发布在  Swift
关注(0)|答案(4)|浏览(115)

我想写一些自定义测试Assert类型,并将它们显示在Xcode中,类似于XCTAssert()失败的显示方式:


的数据
有没有一种方法可以让我连接到Xcode并实现这一点?
我希望我自己的Assert函数以同样的方式内联显示它的错误:



到目前为止,我找到的最好的资源是Apple的XCTest source code,但我还不知道它是否包括负责显示错误UI的逻辑。

tzxcd3kk

tzxcd3kk1#

最简单的方法是从您的自定义Assert调用XCTFail(),但要沿着调用站点的文件名和行号。举例来说:

func verify(myThing: MyThing, file: StaticString = #filePath, line: UInt = #line) {
   // Do your verification. Then when you want to fail the test,
   XCTFail("Some message about \(myThing)", file: file, line: line)
}

字符串
在调用站点,您将让默认参数提供fileline。所以它看起来就像:

verify(myThing: thing)


在Swift中,XCTestAssert是全局函数。这意味着你的helper也可以是一个全局函数,并且在测试套件中共享,而不必子类化XCTestCase

exdqitrt

exdqitrt2#

完全有可能做到你所希望的,我只是设法做到了,就像这样:

使用recordFailure

在任何测试中,只需调用recordFailure(继承自标准XCTestCase),就可以实现您想要的结果。

更短的语法

扩展XCTestCase

如果你想简化对这个函数的调用,你可以写一个扩展函数来 Package 它。

或子类

您也可以子类化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方法(源代码)的一个必需参数,但看起来苹果大多数情况下都将其设置为false

自定义Assert方法

现在,您可以声明自定义的assert方法,如下所示(或者仅作为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
        )
    }

}


现在它报告错误,**不是在自定义Assert内,而是在调用点。

使用标准Assert方法+文件中的转发位置

您也可以只转发的line,并传递给标准Assert,如果您查看例如XCTAssertTrue,它接受行参数和file参数。“

7cwmlq89

7cwmlq893#

有了Xcode 12,我们可以使用XCTIssue内联Assert,现有的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)
        }
    }
}

字符串
下面是失败Assert的屏幕截图


的数据

wz3gfoph

wz3gfoph4#

Xcode 14

一个简单的解决方案是将fileline值从调用站点传递到您的自定义测试Assert中,然后在XCTAssert调用中使用这些值:
自定义测试Assert:

private func verify(_ input: String, formatsTo expectedFormat: String, file: StaticString = #filePath, line: UInt = #line) {
    let result = timeParser.formatTime(string: input)
    XCTAssertEqual(result, expectedFormat, file: file, line: line)
}

字符串
这将提供与本地调用assert相同的失败消息:


的数据

相关问题