@available 属性不适用于 XCTest 类或方法

Oli*_*ain 11 ios xctest swift

我希望单元测试仅在给定版本的 iOS 或更高版本上运行,但该@available属性似乎根本不适用于 XCTest 方法:-(

例如,我根本无法使用@available关键字的任何变体来禁用测试。无论@available是在类或函数、用途unavailable或任何东西上定义,测试始终执行。例如...

// Still runs on iOS
@available(iOS, unavailable)
class SomeTests: XCTestCase {
    func testSomething() {
        print("operatingSystemVersion=\(ProcessInfo.processInfo.operatingSystemVersion)")
        XCTFail()
    }
}
Run Code Online (Sandbox Code Playgroud)
// Still runs on iOS
class SomeTests: XCTestCase {
    @available(iOS, unavailable)
    func testSomething() {
        print("operatingSystemVersion=\(ProcessInfo.processInfo.operatingSystemVersion)")
        XCTFail()
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以使用下面的方法实现我想要的,但这对于很多测试来说并不实用,容易出错,在运行时确定,并且测试方法仍然执行并显示为成功(事实并非如此)。

class SomeTests: XCTestCase {
    func testSomething() {
        if #available(iOS 10.0, *) {
           print("operatingSystemVersion=\(ProcessInfo.processInfo.operatingSystemVersion)")
           XCTFail()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为预处理器宏没有#if os(...)帮助,因为它不能进行版本检查。

有没有其他方法可以实现我想要的?我做错了什么@available(或者这可能只是一个错误)?

Voj*_*vik 3

我通过为仅 iOS13 的测试创建一个特殊的超类来解决这个问题:


class iOS13TestCase: XCTestCase {
    
    override func invokeTest() {
        if #available(iOS 13, *) {
            return super.invokeTest()
        } else {
            print("Skipping test because it's iOS13+ only.")
            return
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

然后,我在测试中使用它,而不是仅使用 XCTestCase 进行 iOS13 测试:

@available(iOS 13, *)
class SwiftUITest: iOS13TestCase {
    func test_something() { }
}

Run Code Online (Sandbox Code Playgroud)

Xcode 仍然可以看到测试,但是,在低于 iOS13 的版本上会跳过它们的执行。

通过绕过该属性可以更好地解决这个问题XCTestCase.testInvocations。由于NSInvocation在 Swift 中不可用,因此需要在 Objective-C 中实现超类,但我不想这样做:)