如何在Xcode中编写GUI的自动单元测试?

Pat*_*Gee 6 xcode cocoa unit-testing

我想编写一个单独测试我的Cocoa应用程序的GUI部分.

在教科书单元测试中,有一个测试框架和测试用例调用被测单元.该单元下面的所有代码都被模拟了.因此,输入和输出都受到控制和监控; 仅测试被测单元中的代码.

我想做同样的事情,被测单元是我的GUI:
1)设置某种框架,我可以编写代码来操作和检查GUI控件.
2)将我的GUI控件连接到我的实际代码的模拟,而不是实际的实例.
3)运行测试,操作控件然后检查模拟对象以查看是否使用正确的参数调用了正确的方法,并检查GUI以查看来自模拟对象的响应是否导致窗口小部件中的正确更改.

有人这样做吗?如果是这样,怎么样?有关如何做到这一点的任何想法?

谢谢,

(编辑)为了给出一个非常具体的例子,我想:
1)编写一个测试用例,选择菜单项'MyMenu' - >'MyItem'.在这个测试用例中,我想检查一下方法[AppDelegate doMyItem]是否被精确调用一次,并且AppDelegate中没有其他方法被调用.
2)生成AppDelegate的模拟对象.(我知道如何做到这一点)
3)不知何故(在这里handwaving)链接我的应用程序,以便AppDelegate的模拟实例链接而不是真实的.
4)运行测试.看它失败因为1)我还没有创建MyMenu.2)我还没有创建MyItem.3)我没有完成将MyItem连接到[AppDelegate doMyItem]的IB工作,或4)因为我还没有编写'doMyItem'方法.
5)修正上述四个问题(如果那天我感觉真的很迂腐).
6)再次运行测试并观察它是否成功.

这会使问题清楚吗?

pat*_*ros 1

这里有一些常用的方法(应该适用于大多数(如果不是全部)可可兼容语言)。

1 - 创建回调接口。创建 GUI 元素时的输入之一是该接口的实现。当有用户交互时,GUI 元素会调用该界面上的更新函数。有一个实际的实现和一个测试的实现。

2 - 使用事件处理程序。将所有 GUI 元素注册到一个或多个事件处理程序,并让 GUI 在用户交互时生成事件。拥有一个具有两种实现的事件处理程序接口,一种用于实际使用,另一种用于测试。

编辑:哎呀,错过了要求#1。从未使用 OSX 特定控件完成此操作,但通常有两种方法。

1 - 创建一个脚本或应用程序来生成类似用户的输入。缺点是实际检查 GUI 并不容易。相反,您需要生成良好的测试用例,以确保应有的一切都存在,并且没有多余的东西。

2 - 创建一个带有测试实现的界面,替换渲染和界面层。对于 SDL 或 directFB 之类的库来说,这更容易,而对于 OSX API、win32 API 等库来说,则不然。

编辑:回应有问题的编辑。

在您的示例中,使用单独的测试应用程序和事件处理程序如下所示:

您的测试应用程序是一个简单的应用程序或脚本,用于启动 GUI,然后根据输入文件生成鼠标/键盘事件。正如我所说,从未在 OSX 中这样做过(仅 QNX)。运气好的话,您将能够使用 API 生成鼠标和键盘事件,但您必须询问其他人是否可能。

因此,为您的测试用例创建一个输入。测试应用程序将解析它以了解要做什么。它可能是像这样的简单 XML:

<testcase name="blah"><mouseevent x="120" y="175" type="click"/></testcase>
Run Code Online (Sandbox Code Playgroud)

或者无论鼠标序列实际上是什么。

当您的脚本执行该命令时,它将在该按钮上单击鼠标。您的事件处理程序将注意到这一点。但现在您应该使用 --test 标志或类似标志运行您的应用程序,以便它实际上使用测试事件处理程序。测试事件处理程序可以执行一些自定义操作,而不是执行应用程序通常执行的任何操作。例如,它可能会执行一些正常操作(您仍然需要 GUI 来响应),然后向您的测试应用程序发送消息(通过套接字、管道等)。

您的测试应用程序将获取此消息并将其与预期看到的内容进行比较。现在,您的测试用例 XML 可能如下所示:

<testcase name="blah">
   <mouseevent x="120" y="175" type="click"/>
   <response>doMyItem() called</response>
</testcase>
Run Code Online (Sandbox Code Playgroud)

如果事件处理程序生成的响应不同,则测试用例失败。您可以打印出实际响应以帮助调试。