用于 UI 测试的台风交换组件

Typhoon swap assembly for UI testing

在 iOS 上运行 UI 测试时是否可以交换或修补程序集?目前我有一个项目,我在其中设置了 Typhoon 框架,我能够像这样修补程序集

var controller: HomeViewController!

override func setUp() {
    super.setUp()
    // setup assemblies
    var blAssembly = BusinessLogicAssembly()
    var ctrlAssembly = AppAssembly()

    // setup patcher
    let patcher = TyphoonPatcher()
    patcher.patchDefinitionWithSelector("testManager", withObject: {return FakeManager()})

    patcher.patchDefinition(blAssembly.testManager() as TyphoonDefinition, withObject: {
        return FakeManager()})


    let factory = TyphoonBlockComponentFactory(assemblies: [blAssembly, ctrlAssembly])
    factory.attachPostProcessor(patcher)


    // get controller
    controller = factory.componentForKey("homeViewController") as HomeViewController

    // force view to laod
    let vcView = controller.view
}

这工作正常。它用存根修补 TestManager。但在这种情况下,我手动调用我的视图控制器。当我运行 UI 测试时(当应用程序启动时,控制器在幕后处理)是否有办法修补程序集并提供 mock/stub?

例如,假设我有一个调用 Web 服务的视图控制器。 Web 服务逻辑包装在一个单独的 class 中,并使用 TyphoonAssembly 注入到视图控制器中。现在,对于我的 UI 测试,我不想联系我的实际 Web 服务,而只是证明示例数据。我想象通过创建我的 Web 服务存根 class 并返回测试数据来实现这一点。这个可以用Typhoon框架实现吗,因为我做不到,也找不到例子。

我正在使用 Swift,但 Objective-C 答案也可以(只要兼容)

现在 Typhoon 有几种方法可以将一个组件换成另一个。我们可以使用 TyphoonPatcher or modularize assemblies. Or we could even make a custom TyphoonDefinitionPostProcessor 或 TyphoonInstancePostProcessor.

problem/solution:

但是如果我正确理解你的问题,问题是正在使用应用程序样式(默认)类型的测试,其中:

  • TEST_HOST 标志已设置。您的应用程序 类 对您的测试可见。
  • 集成测试实例化它们自己的程序集,而不是使用应用程序程序集。虽然通常建议这样做,但重要的是要注意这是 一个单独的、附加的 程序集到主应用程序中使用的程序集。

如果您想从测试中修改主应用程序的程序集,我们可以使用 defaultFactory。如果您使用的是 plist 集成:

为您的应用委托创建一个定义:

 dynamic func appDelegate() -> AnyObject {
    return TyphoonDefinition.withClass(AppDelegate.self) {
        (definition) in

        //This is a public instance var of type TyphoonComponentFactory
        definition.injectProperty("assembly", with: self)
    }
}    

。 .然后在你的 AppDelegate 中:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    factory.makeDefault()

}

。 . .现在在你的测试中或任何你需要的地方,你通过获取一个钩子来修补应用程序的程序集:

TyphoonComponentFactory *factory = [TyphoonComponentFactory defaultFactory];
[factory unload]; //clear out any singletons
//Now patch it
  • 请注意,您可能需要先调用 factory.unload() 清除任何 TyphoonScopeSingleton 实例。
  • 另请注意,如果您愿意,TyphoonPatcher 还允许取消修补或回退。

选择:

或者,更简单(我们建议尽可能简单),也许您可​​以使用不同的网络程序集启动应用程序,在应用程序 plist 中指定一组不同的程序集。



*注意:在 Objective-C 中,任何 TyphoonComponentFactory 都可以转换为程序集,反之亦然。这在 Swift 中是不允许的,因此可能会造成一些不便的限制。由 #253

致辞