iOS 测试/规范 TDD/BDD 和集成与验收测试

Posted

技术标签:

【中文标题】iOS 测试/规范 TDD/BDD 和集成与验收测试【英文标题】:iOS Tests/Specs TDD/BDD and Integration & Acceptance Testing 【发布时间】:2011-05-06 01:43:51 【问题描述】:

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


Unit Testing

Test::Unit风格

    OCUnit/SenTestingKit 如ios Development Guide: Unit Testing Applications 和其他OCUnit references 中所述。 示例:iPhoneUnitTests、Three20 CATCH GHUnit Google Toolbox for Mac: iPhone Unit Testing

RSpec风格

    Kiwi(还带有嘲讽和期望) Cedar Jasmine 和 UI Automation 如dexterous' iOS-Acceptance-Testing specs 所示

Acceptance Testing

Selenium风格

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

    UI Automation Instruments Guide UI Automation reference documentation Tuneup js - 与 UIAutomation 一起使用的酷库。

    Capturing User Interface Actions into Automation Scripts

    可以使用Cucumber (written in javascript) 来驱动 UI 自动化。这将是一个很棒的开源项目。然后,我们可以写Gherkin 来运行 UI 自动化测试。现在,我将把 Gherkin 写成 cmets。

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

    旧博客文章:

    Alex Vollmer's UI Automation tutorial O'Reilly Answers UI Automation tutorial Adi Saxena's UI Automation tutorial

    UISpec 和 UISpecRunner

    UISpec is open source on Google Code。 UISpec has comprehensive documentation。

    FoneMonkey

Cucumber风格

    Frank 和iCuke(基于Cucumber meets iPhone talk)

    Frank Google Group 的活动比iCuke Google Group 多得多。 Frank 可在设备和模拟器上运行,而 iCuke 仅在模拟器中运行。 Frank 似乎拥有比iCuke's step definitions 更全面的步骤定义集。还有,Frank also has a step definition compendium on their wiki。 I proposed that we merge iCuke & Frank(类似于 Merb 和 Rails 的合并方式)因为它们有相同的共同目标:Cucumber for iOS。

    KIF (Keep It Functional)Square

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

补充

OCMock 为mocking OCHamcrest 和/或 Expecta 期待

结论

嗯,很明显,这个问题没有正确答案,但这是我目前选择的答案:

对于单元测试,我曾经在 XCode 4 中使用OCUnit/SenTestingKit。它简单而可靠。但是,我更喜欢 BDD 语言而不是 TDD (Why is RSpec better than Test::Unit?),因为我们的语言创造了我们的世界。所以现在,我使用Kiwi with ARC & Kiwi code completion/autocompletion。我更喜欢 Kiwi 而不是 Cedar,因为它建立在 OCUnit 之上,并带有 RSpec 风格的匹配器和模拟/存根。更新:我现在正在研究 OCMock,因为目前,Kiwi doesn't support stubbing toll-free bridged objects。

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

您使用哪些解决方案?

相关问题

Is there a BDD solution that presently works well with iOS4 and Xcode4? SenTestingKit (integrated with XCode) versus GHUnit on XCode 4 for Unit Testing? Testing asynchronous code on iOS with OCunit SenTestingKit in Xcode 4: Asynchronous testing? How does unit testing on the iPhone work?

【问题讨论】:

我至少在几个月前就知道关键实验室正在使用雪松。 (嗯,我想这很明显,因为它在他们的 github 帐户上)。在这样的商店的支持下,这将是我的选择。 这很好。但是话又说回来,Apple 会建议使用他们的单元测试框架,而不是 Cedar,不是吗?所以,然后是 Pivotal Vs。苹果。选哪个? 我写了一篇比较 Frank、KIF 和 UIAutomation 的帖子,这个帖子的读者可能会感兴趣 sgleadow.github.com/blog/2011/10/26/… 【参考方案1】:

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 语法)。当购物车为空时,与购物车包含其他物品时相比,此方法的行为可能有所不同;如果用户输入了折扣代码,它可能会有所不同;如果指定的物品无法通过所选的运输方式运输,则可能会有所不同;等等。当这些可能的条件相互交叉时,你最终会得到几何上增加的可能上下文;在 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。

【讨论】:

感谢您的彻底回复。我将阅读 RSpec 书并尝试 Ceder。我将 UISpec 移至 Selenium 部分并在那里添加了 UIAutomation。我正在阅读您关于 UIAutomation 的博客文章。 Frank 实际上看起来更简单、更易读,而且文档也更好,所以我正在考虑从它开始。我只希望它和 UIAutomation 一样强大。你说 UIAutomation 可以测试生命周期问题。我想知道 iCuke 是否也可以...【参考方案2】:

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

【讨论】:

【参考方案3】:

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

【讨论】:

谢谢。我看到了那个,但忘了提。 GHUnit 的 PLus 1。与OCMock一起使用了很多。设置、扩展和工作非常可靠是一件轻而易举的事。【参考方案4】:

伟大的名单!

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

Zucchini Framework

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

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

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

【讨论】:

紧!谢谢。我在上面的问题中添加了这个。【参考方案5】:

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

【讨论】:

【参考方案6】:

GHUnit 适合单元测试;对于集成测试,我使用 UISpec 取得了一些成功(github fork here:https://github.com/drync/UISpec),但我期待尝试 iCuke,因为它有望成为轻量级设置,并且您可以使用 Rails 测试优点,如 RSpec和黄瓜。

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

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

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

https://github.com/ericmeyer/ocdspec2

【讨论】:

以上是关于iOS 测试/规范 TDD/BDD 和集成与验收测试的主要内容,如果未能解决你的问题,请参考以下文章

软件开发方法论:TDDBDDDDDATDDDevOps

软件开发方法论:TDDBDDDDDATDDDevOps

TDDBDDATDDDDD 软件开发模式

Sql 或 Reports 的验收测试

iOS测试与集成

iOS测试与集成