0

我正在尝试对一个在 viewController 之外呈现视图的函数进行单元测试:

public func presentInOwnWindow(animated: Bool, completion: (() -> Void)?) {
        let alertWindow = UIWindow(frame: UIScreen.main.bounds)
        alertWindow.rootViewController = UIViewController()
        alertWindow.windowLevel = UIWindowLevelAlert + 1;
        alertWindow.makeKeyAndVisible()
    alertWindow.rootViewController?.present(self, animated: animated, completion: completion)
    }

到目前为止,我所能想到的如何对它进行单元测试是这样的:

  func test_presentInOwnWindow () {

       let presented = sut.presentInOwnWindow(animated: true) {}

        XCTAssertNotNil(presented)
    }

我尝试为完成块传递一个布尔值:

完成:((布尔)-> 无效)

但由于它调用完成:

rootViewController?.present

我得到错误:

无法转换类型“((Bool)-> Void)的值?” 到预期的参数类型'(() - > Void)?

知道如何正确地对功能进行单元测试吗?

4

2 回答 2

0

几个选项可以尝试:

  1. Swizzle UIViewControllerpresent(_, animated, completion)捕捉呈现的内容。我为 UIAlertControllers https://qualitycoding.org/testing-uialertcontroller/这样做是因为 UIAlertControllers 很常见。您的自定义窗口可能不值得麻烦。
  2. 不确定这是否可行。makeKeyAndVisible并且present可能不会产生立竿见影的效果。相反,他们安排工作。因此,您可以尝试使用RunLoop.current.run(until: Date()). 这适用于激活文本字段,但我不知道它是否适合您。
  3. 同样,尝试添加一个 XCTestExpectation 并waitForExpectations设置一个小超时。正如我在https://qualitycoding.org/asynchronous-tests/中指出的那样,不要在您的期望处理程序中做任何断言。相反,捕捉你想要的信息和fulfill期望。然后断言你所捕获的。
  4. 更改您编写的代码以使其更易于测试。通过调用保存在 SUT 的属性中的块来替换最后一行。为了测试,更换这个块。测试块可以调用完成处理程序,这为您提供了一种测试处理程序的方法。
  5. 手动测试此代码以使您满意。然后围绕它进行模拟,以便您的测试检查是否调用了此方法(但实际上并未调用它)。
于 2018-02-17T19:20:36.093 回答
0

具有副作用的单元测试代码可能非常困难,特别是如果副作用涉及硬件,例如设备屏幕。由于这个原因,UI 组件不适合单元测试,因为它们通常涉及 GPU 操作。

现在,如果你真的想测试组件,你可以通过两条路线:

  • 你写快照测试
  • 您将所有业务逻辑提取到专用类中并对其进行测试。

结论:对业务代码进行单元测试,让 QA 测试 UI 的行为是否符合预期。

于 2018-02-17T07:03:30.137 回答