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

标签 xcode swift xctest dependency-inversion

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

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

enter image description here

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

class WhiteboardRepositoryTests: XCTestCase {
  var repo: WhiteboardRepository?

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

  // test cases here

}

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

例如,这是 WhiteboardRepositoryFakeTests 的样子:

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

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

当然,这工作正常,因为 WhiteboardRepositoryFakeTestsWhiteboardTests 包中,所以 WhiteboardRepositoryTests 暴露给 WhiteboardRepositoryFakeTests.

问题是:链接到 Whiteboard 的应用需要创建它们自己的 WhiteboardRepositoryTests 子类来测试它们自己的实现,但是因为它们无权访问WhiteboardTests 测试包,他们不知道 WhiteboardRepositoryTests 类,因此不能将其子类化。

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

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

最佳答案

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

  1. 点击项目文件,然后点击编辑器 > 添加目标,在您的白板项目中创建框架构建目标。我们暂时将此称为 WhiteboardAbstractTests。该目标将与 XCTest 链接并构建一个框架来提供您希望客户端项目的测试子类化的父类(super class)。

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

  3. 从这里开始,您应该能够在将构建到 WhiteboardAbstractTests.framework 中的 WhiteboardAbstractTests 中定义 XCTestCase 子类。

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

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

  6. 同样在构建阶段的“将二进制文件与库链接”下,选择 WhiteboardAbstractTests 以确保我们的测试目标链接并可以从 Whiteboard 提供的抽象测试中导入类。

从这里您应该能够在您的客户端项目中运行测试,该项目将构建 WhiteboardAbstractTests,将您的客户端测试与之链接,并运行您的客户端测试,该测试将抽象测试子类化。我已经快速测试了它,但如果您遇到问题,请告诉我。

附言我喜欢你的建筑风格。马丁·福勒 (Martin Fowler) 在某处流下了喜悦的泪水。

关于xcode - 如何将 XCTestCases 公开给外部测试包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38277720/

相关文章:

ios - 如何使用 KIF 自动 UIPickerView 选择特定项目?

xcode - 如何更新Xcode的SQLITE3版本?

ios - Xcode 中的小数位显示不正确?

ios - Apple map 样式菜单弹出窗口

objective-c - 为什么当我测试一个方法抛出异常并且该方法抛出异常时,测试会停止?

swift - 在 Swift 中向 OSX 项目添加测试时无法访问主要目标方法

ios - 如何在首次启动时仅显示一次 UIPageViewController

ios - ' fatal error : NSCoder not supported' when using UIViewController

ios - 实现 Alamofire.NetworkReachabilityManager 供全局使用

ios - SpriteKit 背景 PNG,Alpha 显示黑色