229

在 iPhone 上用于行为驱动开发的最佳技术是什么?有哪些开源示例项目可以证明这些技术的合理使用?以下是我发现的一些选项:


单元测试

测试::单元样式

  1. OCUnit/SenTestingKitiOS 开发指南:单元测试应用程序和其他OCUnit 参考中所述。
  2. 抓住
  3. GH单元
  4. 适用于 Mac 的 Google 工具箱:iPhone 单元测试

RSpec风格

  1. 猕猴桃(也带有嘲弄和期望)
  2. 雪松
  3. 带有UI 自动化的Jasmine ,如dexterous 的 iOS-Acceptance-Testing 规范中所示

验收测试

风格

  1. UI 自动化(在设备上工作)

    更新:Zucchini 框架似乎融合了 Cucumber 和 UI 自动化!:)

    旧博客文章:

  2. UISpecUISpecRunner

  3. FoneMonkey

黄瓜风格

  1. FrankiCuke(基于Cucumber 与 iPhone 的对话

  2. SquareKIF(保持功能)

  3. Zucchini Framework使用 Cucumber 语法编写测试,并使用 CoffeeScript 进行步骤定义。

加法

结论

好吧,显然,这个问题没有正确的答案,但这是我目前选择的:

对于单元测试,我曾经在 XCode 4中使用OCUnit/SenTestingKit 。它简单而可靠。但是,我更喜欢 BDD 语言而不是 TDD(为什么 RSpec 比 Test::Unit 更好?),因为我们的语言创造了我们的世界。所以现在,我将Kiwi 与 ARCKiwi 代码完成/自动完成一起使用。我更喜欢 Kiwi 而不是 Cedar,因为它建立在 OCUnit 之上,并带有 RSpec 风格的匹配器和模拟/存根。更新:我现在正在研究 OCMock,因为目前Kiwi 不支持存根免费桥接对象

对于验收测试,我使用 UI 自动化,因为它很棒。它使您可以记录每个测试用例,从而自动编写测试。此外,Apple 开发了它,因此它有一个充满希望的未来。它也适用于设备和 Instruments,它允许其他很酷的功能,比如显示内存泄漏。不幸的是,使用 UI 自动化,我不知道如何运行 Objective-C 代码,但使用 Frank 和 iCuke,你可以。因此,我将只使用单元测试来测试较低级别的 Objective-C 内容,或者UIButton仅为TEST构建配置创建 s ,单击它时将运行 Objective-C 代码。

您使用哪些解决方案?

相关问题

4

8 回答 8

53

tl;博士

在 Pivotal,我们编写 Cedar 是因为我们在 Ruby 项目中使用并喜欢 Rspec。Cedar 并不是要取代 OCUnit 或与 OCUnit 竞争。它旨在为 Objective C 带来 BDD 样式测试的可能性,就像 Rspec 在 Ruby 中开创了 BDD 样式测试一样,但并未消除 Test::Unit。选择其中一个很大程度上取决于风格偏好。

在某些情况下,我们设计 Cedar 是为了克服 OCUnit 为我们工作的方式中的一些缺点。具体来说,我们希望能够在测试中使用调试器,从命令行和 CI 构建中运行测试,并获得有用的测试结果文本输出。这些东西可能或多或少对你有用。

长答案

在 Cedar 和 OCUnit 等两个测试框架之间做出决定(例如)归结为两件事:首选风格和易用性。我将从风格开始,因为这只是意见和偏好的问题;易用性往往是一系列权衡。

风格考虑超越了您使用的技术或语言。xUnit 风格的单元测试比 BDD 风格的测试存在的时间要长得多,但后者迅速流行起来,主要是由于 Rspec。

xUnit 风格测试的主要优点是它的简单性和广泛采用(在编写单元测试的开发人员中);几乎任何您可以考虑使用其编写代码的语言都有可用的 xUnit 风格的框架。

与 xUnit 风格相比,BDD 风格的框架往往有两个主要区别:如何构建测试(或规范),以及编写断言的语法。对我来说,结构上的差异是主要的区别。xUnit 测试是一维的,给定测试类中的所有测试都有一个 setUp 方法。然而,我们测试的类不是一维的。我们经常需要在几个不同的、可能相互冲突的上下文中测试操作。例如,考虑一个带有 addItem: 方法的简单 ShoppingCart 类(出于本答案的目的,我将使用 Objective C 语法)。当购物车为空时,与购物车包含其他物品时相比,此方法的行为可能有所不同;如果用户输入了折扣代码,它可能会有所不同;如果指定的项目可以,它可能会有所不同' t 通过所选的运输方式运输;等等。当这些可能的条件相互交叉时,你最终会得到几何上增加的可能上下文;在 xUnit 风格的测试中,这通常会导致很多方法名称为 testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies。BDD 风格框架的结构允许您单独组织这些条件,我发现这样可以更轻松地确保涵盖所有情况,也更容易找到、更改或添加单个条件。例如,使用 Cedar 语法,上面的方法如下所示:在 xUnit 风格的测试中,这通常会导致很多方法名称为 testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies。BDD 风格框架的结构允许您单独组织这些条件,我发现这样可以更轻松地确保涵盖所有情况,也更容易找到、更改或添加单个条件。例如,使用 Cedar 语法,上面的方法如下所示:在 xUnit 风格的测试中,这通常会导致很多方法名称为 testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies。BDD 风格框架的结构允许您单独组织这些条件,我发现这样可以更轻松地确保涵盖所有情况,也更容易找到、更改或添加单个条件。例如,使用 Cedar 语法,上面的方法如下所示:

describe(@"ShoppingCart", ^{
    describe(@"addItem:", ^{
        describe(@"when the cart is empty", ^{
            describe(@"with no discount code", ^{
                describe(@"when the shipping method applies to the item", ^{
                    it(@"should add the item to the cart", ^{
                        ...
                    });

                    it(@"should add the full price of the item to the overall price", ^{
                        ...
                    });
                });

                describe(@"when the shipping method does not apply to the item", ^{
                    ...
                });
            });

            describe(@"with a discount code", ^{
                ...
            });
        });

        describe(@"when the cart contains other items, ^{
            ...
        });
    });
});

在某些情况下,您会发现其中包含相同的断言集的上下文,您可以使用共享的示例上下文将其干燥。

BDD 风格的框架和 xUnit 风格的框架之间的第二个主要区别,断言(或“匹配器”)语法,只是使规范的风格更好一些。有些人真的很喜欢,有些人不喜欢。

这就引出了易用性的问题。在这种情况下,每个框架都有其优点和缺点:

  • OCUnit 的存在时间比 Cedar 长得多,并且直接集成到 Xcode 中。这意味着创建一个新的测试目标很简单,并且在大多数情况下,启动和运行测试“正常工作”。另一方面,我们发现在某些情况下,例如在 iOS 设备上运行,让 OCUnit 测试工作几乎是不可能的。设置 Cedar 规范比 OCUnit 测试需要更多的工作,因为你已经获得了库并自己链接它(在 Xcode 中绝不是一项微不足道的任务)。我们正在努力简化设置,欢迎提出任何建议。

  • OCUnit 作为构建的一部分运行测试。这意味着您无需运行可执行文件即可运行测试;如果任何测试失败,您的构建就会失败。这使运行测试的过程更简单了一步,测试输出直接进入您的构建输出窗口,便于查看。我们选择将 Cedar 规范构建到您单独运行的可执行文件中,原因如下:

    • 我们希望能够使用调试器。您可以像运行任何其他可执行文件一样运行 Cedar 规范,因此您可以以同样的方式使用调试器。
    • 我们想要简单的控制台登录测试。您可以在 OCUnit 测试中使用 NSLog(),但输出会进入构建窗口,您必须展开构建步骤才能阅读它。
    • 我们希望在命令行和 Xcode 中都易于阅读测试报告。OCUnit 结果很好地显示在 Xcode 的构建窗口中,但是从命令行构建(或作为 CI 过程的一部分)会导致测试输出与大量其他构建输出混合在一起。通过单独的构建和运行阶段,Cedar 将输出分开,因此测试输出很容易找到。默认的 Cedar 测试运行器复制标准样式的打印“.”。对于每个通过的规范,“F”代表失败的规范等。Cedar 还具有使用自定义报告对象的能力,因此您可以让它以您喜欢的任何方式输出结果,只需一点点努力。
  • OCUnit 是 Objective C 的官方单元测试框架,得到 Apple 的支持。苹果基本上拥有无限的资源,所以如果他们想要做某事,它就会完成。而且,毕竟,这是我们正在玩的 Apple 的沙盒。然而,硬币的另一面是,Apple 每天都会收到数以亿计的支持请求和错误报告。他们非常擅长处理所有问题,但他们可能无法立即或根本无法处理您报告的问题。Cedar 比 OCUnit 更新且不那么成熟,但是如果您有任何疑问或问题或建议,请向 Cedar 邮件列表 (cedar-discuss@googlegroups.com) 发送消息,我们将尽我们所能为您提供帮助。此外,请随时从 Github (github.com/pivotal/cedar) 分叉代码并添加您认为缺少的任何内容。

  • 在 iOS 设备上运行 OCUnit 测试可能很困难。老实说,我已经有一段时间没有尝试过这个了,所以它可能变得更容易了,但我最后一次尝试时,我根本无法让任何 UIKit 功能工作的 OCUnit 测试。当我们编写 Cedar 时,我们确保我们可以在模拟器和设备上测试依赖于 UIKit 的代码。

最后,我们为单元测试编写了 Cedar,这意味着它无法与 UISpec 之类的项目真正相提并论。自从我尝试使用 UISpec 以来已经有一段时间了,但我理解它主要专注于以编程方式驱动 iOS 设备上的 UI。我们特别决定不尝试让 Cedar 支持这些类型的规范,因为 Apple(当时)即将宣布 UIAutomation。

于 2010-11-06T20:35:47.020 回答
8

我将不得不把弗兰克扔进验收测试组合中。这是一个相当新的添加,但到目前为止对我来说效果很好。此外,与 icuke 和其他人不同,它实际上正在积极开发中。

于 2011-03-05T15:43:39.810 回答
5

对于测试驱动的开发,我喜欢使用GHUnit,它的设置很容易,而且也非常适合调试。

于 2010-11-06T20:40:33.740 回答
4

伟大的名单!

我发现了另一个有趣的 UI 测试 iOS 应用程序的解决方案。

西葫芦框架

它基于UIAutomation. 该框架允许您以 Cucumber 风格编写以屏幕为中心的场景。这些场景可以在模拟器中执行,也可以通过控制台在设备上执行(它是 CI 友好的)。

断言是基于屏幕截图的。听起来不灵活,但它会为您提供不错的 HTML 报告,突出显示屏幕比较,并且您可以提供定义您希望具有像素精确断言的区域的掩码。

每个屏幕都必须在其中进行描述,CoffeScript并且它本身的工具是用 ruby​​ 编写的。这是一种多语言的噩梦,但该工具提供了一个很好的抽象,UIAutomation并且当描述屏幕时,即使对于 QA 人员来说也是可以管理的。

于 2012-01-04T13:54:06.743 回答
2

我会选择 iCuke 进行验收测试,选择 Cedar 进行单元测试。UIAutomation 是 Apple 朝着正确方向迈出的一步,但这些工具需要更好地支持持续集成;例如,目前无法使用 Instruments 自动运行 UIAutomation 测试。

于 2010-11-06T21:37:30.350 回答
1

GHUnit 适合单元测试;对于集成测试,我使用 UISpec 取得了一些成功(这里的 github 分支:https ://github.com/drync/UISpec ),但我期待尝试 iCuke,因为它有望成为一个轻量级的设置,你可以使用 Rails 测试善良,如 RSpec 和 Cucumber。

于 2010-11-19T22:51:13.417 回答
1

我目前将specta用于 rspec 之类的设置,它的合作伙伴(如上所述)expecta有很多很棒的匹配选项。

于 2013-04-18T02:02:54.623 回答
0

我碰巧真的很喜欢 OCDSpec2,但我有偏见,我编写了 OCDSpec 并为第二个做出了贡献。

即使在 iOS 上它也非常快,部分原因是它是从头开始构建的,而不是放在 OCUnit 之上。它也有 RSpec/Jasmine 语法。

https://github.com/ericmeyer/ocdspec2

于 2013-08-22T16:28:30.890 回答