背景
我正在寻找一种方法来实现一个类似于Frank库用来实现"本地iOS应用程序的自动验收测试"的方案,但我希望这个方案依赖于本地iOS/AcOSX技术。很抱歉出现以下TLDR
,但需要详细解释。
1.以下是Frank工作原理的简要概述:
它有客户端和服务器两部分。
服务器部分嵌入到我们想要运行验收测试的应用程序中。Frank教程向我们展示了如何创建应用程序主目标的重复目标,并将Frank HTTP服务器嵌入其中
客户端部分-主要是一个运行纯文本场景的Cucumber:每个场景都包含应该针对应用程序运行的指令(填充文本字段、触摸按钮、确保页面上存在特定元素等)。此外,每个场景都会启动自己的应用程序实例,这意味着每次进入新场景时都会提供一个新的状态。
客户端(Cucumber和Ruby-to-Objective-C桥)通过HTTP协议与服务器(嵌入应用程序的HTTP服务器)通信。它使用特殊的约定,这样客户端就可以告诉服务器应用程序应该做什么,这样就可以执行特定的场景。
2.最近我发现了以下由Frank Pete Hodgson的作者撰写的文章:
http://blog.thepete.net/blog/2012/11/18/writing-ios-acceptance-tests-using-kiwi/
在书中,他为那些不喜欢依赖Cucumber和Ruby等外部工具的开发人员提出了更简单的验收测试编写方法。让我引用作者本人的话:
在开始之前,让我明确一点,我个人不会使用这种方法来编写验收测试。我更喜欢使用像ruby这样的高级语言来编写这类测试。假设您对ruby感到满意,那么测试代码的工作量要小得多,表达能力也要强得多。这就是为什么我想尝试这个实验。随着时间的推移,我已经和很多iOS开发人员谈过了,他们对用ruby编写测试感到不舒服。他们在Objective-C中比其他任何东西都更得心应手,并且希望用与生产代码相同的语言编写测试。很公平。
这篇博客文章激发了我快速推出自己的原始工具的灵感,该工具正是Pete在他的博客文章中所描述的:NativeAutomation。
事实上,正如Pete所描述的那样,只需在一个简单的OCTests目标中使用Kiwi/PublicAutomation设置就可以运行验收测试。我真的很喜欢它,因为:
- 它只是纯C/Objective-C。构建最初的C助手非常容易,它们看起来像Capybara助手:
tapButtonWithTitle、fillTextFieldWithPlaceholder、hasLabelWithTitle等…
-
它不需要外部工具和语言:不需要Cucumber/Ruby或其他任何东西。NativeAutomation本身只使用Frank也使用的PublicAutomation。PublicAutomation需要模拟应用程序屏幕上的用户交互:触摸、填充、手势。。。
-
只需运行一个Cocoa单元测试包,就可以直接从Xcode运行这些测试,这非常方便。(尽管命令行构建也很容易)。
问题
Kiwi/PublicAutomation
方法的问题在于,整个测试套件都嵌入到了应用程序的捆绑包中。这意味着在每个场景运行后,在下一个场景开始执行之前,不可能重置应用程序以强制其处于新状态。解决这个问题的唯一方法是用一种方法编写Kiwi's beforeEach
钩子,该方法可以执行应用程序的软重置,如:
+ (void)resetApplication {
[Session invalidateSession];
[LocationManager resetInstance];
[((NavigationController *)[UIApplication sharedApplication].delegate.window.rootViewController) popToRootViewControllerAnimated:NO];
[OHHTTPStubs removeAllStubs];
cleanDatabase();
shouldEventuallyBeTrue(^BOOL{
return FirstScreen.isCurrentScreen;
});
但是,在涉及网络、异步作业、核心数据和文件操作的应用程序中,很难对以前场景中留下的东西进行真正的分解。
问题
上面描述的问题让我思考是否有可能实现一种类似于Frank方法的更复杂的方法,使用第二个独立于主应用程序捆绑包的应用程序,并且不依赖于Cucumber(Ruby)等外部工具。
以下是我如何看待它可以做到的。
除了主应用程序(MainApp)之外,还有第二个iOS(或Mac OS X)应用程序(AcceptanceTestsRunnerApp),它包含整个验收测试套件,并针对主应用程序捆绑包运行该套件:
它在进入每个新场景之前启动新的模拟器实例,并针对当前模拟器的应用程序实例执行当前场景。
问题是:
我对允许我这样做的Mac OSX或iOS技术不太了解:我不知道是否有可能设置一个Mac OS X/iOS应用程序(AcceptanceTestsRunnerApp),它可以控制主应用程序(MainApp)并对其运行验收测试场景。
对于那些对使用本机Objective-C工具为iOS应用程序编写验收测试感到更舒服的人,我将感谢他们的任何想法/建议。
更新后
我确实读过一些关于XPC服务的文档,但具有讽刺意味的是,我正在寻找的方案应该与XPC文档建议的方案完全相反:
理想情况下,我希望我的AcceptanceTestsRunnerApp控制MainApp:通过代理到MainApp的应用程序委托的一些对象来运行它并控制它(用户交互、关于视图层次结构的断言),而XPC服务设置会假设XPC服务(AcceptanceTestsRunnerApp)从属于应用程序(MainApp),并要求XPC服务位于应用程序的捆绑包中,我希望通过一切手段。
我目前阅读的是分布式对象编程主题。在我看来,我会在那里找到答案的。如果没有人给我提供指导,我会发布一个关于我自己研究和想法的答案。
这是我探索的下一步:iOS上的分布式对象。
然而,我也有很多葫芦的好用法,它和弗兰克一样,都是由小黄瓜提供动力的。