如何将 XCTestCases 公开给外部测试包?

How to expose XCTestCases to external test bundles?

我有一个框架 Whiteboard 封装了我的业务逻辑。我试图保持我的依赖倒置和解耦,所以由于 Whiteboard 依赖于存储库,它声明了一个协议 WhiteboardRepository,并且它期望客户端 link 反对 Whiteboard提供 WhiteboardRepository.

的实现

您可以在下面的屏幕截图中看到这一点。还要注意 WhiteboardTests 组,其中包括一个 WhiteboardRepositoryTests class 以及一个 WhiteboardRepositoryFake 和它自己的测试子 class.

为了确保 WhiteboardRepository 的实现按预期运行,WhiteboardTests 测试包定义了 XCTestCaseWhiteboardRepositoryTests subclass:

class WhiteboardRepositoryTests: XCTestCase {
  var repo: WhiteboardRepository?

  override func setUp() {
    if let repo = repo {
      // test setup here
    }
  }

  // test cases here

}

为了让 Whiteboard 的客户端测试其 WhiteboardRepository 的实现,实现子 class 的测试 class 是 WhiteboardRepositoryTests并向测试子 class 提供一个实现实例,然后在 运行 测试时使用该实例。

例如,WhiteboardRepositoryFakeTests 看起来像这样:

class WhiteboardRepositoryFakeTests: WhiteboardRepositoryTests {
    override func setUp() {
        repo = WhiteboardRepositoryFake()
        super.setUp()
    }

    // the test classes run, using the instance of WhiteboardRepositoryFake()
}

当然,这很好用,因为 WhiteboardRepositoryFakeTestsWhiteboardTests 包中,所以 WhiteboardRepositoryTests 暴露给 WhiteboardRepositoryFakeTests

问题是:link 反对 Whiteboard 的应用需要创建自己的 WhiteboardRepositoryTests 的子 class 来测试自己的实现,但是因为他们不无法访问 WhiteboardTests 测试包,他们不知道 WhiteboardRepositoryTests class,因此无法子 class 它。

我有多个客户端使用 Whiteboard,所以我不能简单地将 WhiteboardRepositoryTests class 复制到每个客户端中 — 我也不想这样做,因为它是Whiteboard 有责任定义 WhiteboardRepository 的行为,因此 WhiteboardRepositoryTests 应该存在于 Whiteboard 的测试包中。在理想情况下,我可以 link 或将 Whiteboard 的测试包注入客户端的测试包,以便 WhiteboardRepositoryTests 暴露给客户端的测试,但我不这样做不知道我该怎么做。

有什么办法绕过这个障碍吗?我如何将 WhiteboardRepositoryTests 公开给客户端测试包中的测试,以便客户端可以确保其 WhiteboardRepository 的实现按预期运行?

这里的主要问题是 WhiteboardTests 目标可能是一个测试目标,实际上并没有构建一个 linkable 框架。这可以防止我们构建另一个从中导入和子类化的目标(您的客户端测试)。例如,您会注意到测试目标缺少用于从框架导出符号的正常 {TARGET_NAME}.h 头文件。我们需要的是构建框架但 link 带有 XCTest 的目标。客户项目的测试目标将 link 使用此框架来导入和子类化它提供的 XCTestCase 类。那么怎么办:

  1. 单击项目文件,然后单击编辑器 > 添加目标,在白板项目中创建框架构建目标。我们暂时将此称为 WhiteboardAbstractTests。该目标将 link 与 XCTest 一起构建一个框架来提供您希望客户项目的测试子类化的超级类。

  2. 现在,使用 XCTest link 有点奇怪,因为它们不再使它在 Xcode 中可用。但是,您仍然可以在 Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks/XCTest.framework 找到 XCTest 框架并将其拖到 Xcode.

  3. 的 WhiteboardAbstractTests 目标文件夹中
  4. 从这里开始,您应该能够在 WhiteboardAbstractTests 中定义 XCTestCase sub类,它将构建到 WhiteboardAbstractTests.framework.

  5. 在您的客户端项目中,我假设 Whiteboard xcodeproj 以某种方式嵌套,由 Cocoapods、Carthage 或 git 子模块嵌套。找到Whiteboard xcodeproj文件,拖入Xcode中的客户端项目测试目标。

  6. Select Xcode 中的客户端项目文件,然后转到构建阶段。在 Target dependencies 下,单击加号按钮,您应该会看到来自 Whiteboard 的各种构建目标。 Select 白板抽象测试。这将确保 Xcode 在构建客户端测试之前构建抽象测试。

  7. 同样在构建阶段,在 Link Binary With Libraries 下,select WhiteboardAbstractTests 以确保我们的测试目标 link 具有并且可以导入 类 来自 Whiteboard 提供的抽象测试。

从这里您应该能够 运行 您的客户端项目中的测试将构建 WhiteboardAbstractTests,link 您的客户端使用它进行测试,并且 运行 您的客户端测试哪个子类抽象测试。我已经快速测试过了,但如果您遇到问题,请告诉我。

P.S。我喜欢你的建筑风格。 Martin Fowler 在某处流下了喜悦的泪水。