【问题标题】:@available attribute does not work with XCTest classes or methods@available 属性不适用于 XCTest 类或方法
【发布时间】:2020-04-25 23:17:21
【问题描述】:

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

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

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

我能够通过以下方式实现我想要的,但这对于许多测试来说并不实用,容易出错,在运行时确定并且测试方法仍然执行并显示为成功(这不是确实如此)。

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

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

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

【问题讨论】:

  • 我认为,如果您提供一些有关您希望通过仅 iOS 测试实现什么的信息,这也可能会有所帮助。一种非自动的方法是拥有多个构建方案,并在某些情况下禁用 iOS 测试并在其他情况下启用。问题仍然是操作系统停用测试是否有意义。视情况而定:)
  • 您确定这是一个实际问题吗?测试很可能会显示在 Xcode 中,但在您执行测试时它不会真正运行。
  • 我刚刚检查过,这在 Xcode 11 中确实被破坏了。看起来像是基于以前的互联网线程的回归
  • @JanBrinker 我已经简化了我的示例以提高获得良好答案的可能性。完整上下文 -> 我正在编写一个可在 Mac 和 iOS 上使用的 SDK/框架,并且测试需要在这两个平台上运行。由于 JSONDecoder 的限制(请参阅stackoverflow.com/questions/59627000),某些单元测试只会在 macOS >= 10.15.1 和 iOS >= 12 上通过,所以我希望某些测试可以在除 macOS
  • @OliverPearmain 向 Apple 提交雷达文件。 Xcode 坏了。

标签: ios swift xctest


【解决方案1】:

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


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

然后我在我的测试中使用它而不是 XCTestCase 用于仅 iOS13 的测试:

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

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

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

【讨论】:

    【解决方案2】:

    这可能是XCTSkip 的一个很好的候选者

    class SomeTests: XCTestCase {
        func testSomething() throws {
            guard #available(iOS 13.0, *) else {
               throw XCTSkip("Unsupported iOS version")
            }
            /// Run iOS 13+ tests
        }
    }
    

    请注意,现在可以将测试函数标记为throws,这是使用XCTSkip API 所必需的。

    【讨论】:

      猜你喜欢
      • 2021-09-16
      • 1970-01-01
      • 1970-01-01
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多