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


229

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


单元测试

测试::单元样式

  1. OCUnit / SenTestingKit,如《iOS开发指南:单元测试应用程序及其他OCUnit参考》中所述
  2. 抓住
  3. GHUnit
  4. Mac版Google工具箱:iPhone单元测试

RSpec样式

  1. 猕猴桃(还带有嘲笑和期望)
  2. 雪松
  3. JasmineUI Automation,如灵巧的iOS接受测试规范中所示

验收测试

风格

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

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

    旧博客文章:

  2. UISpecUISpecRunner

  3. FoneMonkey

黄瓜风格

  1. 弗兰克Frank)伊库克iCuke)(基于黄瓜与iPhone的对话

  2. KIF(保持功能)广场

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

加法

结论

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

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

对于验收测试,我使用UI自动化,因为它很棒。它使您可以记录每个测试用例,从而自动编写测试。另外,苹果公司也在开发它,因此它有光明的未来。它也可以在设备上运行,也可以在Instruments上运行,这允许其他很酷的功能,例如显示内存泄漏。不幸的是,使用UI自动化,我不知道如何运行Objective-C代码,但是使用Frank&iCuke,您可以。因此,我将仅使用单元测试来测试较低级别的Objective-C东西,或者UIButton仅为TEST构建配置创建s ,当其被单击时将运行Objective-C代码。

您使用哪种解决方案?

相关问题


1
我知道至少在几个月前,关键实验室正在使用雪松。(嗯,我猜这在他们的github帐户上很明显)。在这样的商店的支持下,这将是我的选择。
杰德·施耐德

1
那是个很好的观点。但是话又说回来,Apple建议使用其单元测试框架,而不是Cedar,不是吗?因此,这就是PivotalVs。苹果。搭配哪一个?
ma11hew28 2010年

2
我写了一篇比较Frank,KIF和UIAutomation的帖子
Stew

Answers:


53

tl; dr

在Pivotal,我们之所以写Cedar是因为我们在Ruby项目中使用并喜欢Rspec。Cedar并不是要取代OCUnit或与其竞争。就像Rspec率先在Ruby中进行BDD样式测试一样,它的目的是将BDD样式测试的可能性带到Objective C,但并未消除Test :: Unit。选择一个或另一个很大程度上取决于样式偏好。

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

长答案

在两个测试框架(例如Cedar和OCUnit)之间进行选择取决于两件事:首选样式和易用性。我将从样式开始,因为这只是意见和偏好的问题;易用性往往是一系列的权衡。

样式方面的考虑超越了您使用的技术或语言。xUnit风格的单元测试比BDD风格的测试存在更长的时间,但是BDD风格的测试迅速流行,这在很大程度上归功于Rspec。

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

与xUnit风格相比,BDD风格的框架往往有两个主要区别:测试(或规范)的结构方式以及编写断言的语法。对我而言,结构差异是主要差异。xUnit测试是一维的,对于给定测试类中的所有测试都有一个setUp方法。但是,我们测试的类不是一维的。我们经常需要在几种不同的,可能相互冲突的环境中测试动作。例如,考虑一个带有addItem:方法的简单ShoppingCart类(出于此答案的目的,我将使用Objective C语法)。当购物车为空时,与购物车中包含其他物品时相比,此方法的行为可能有所不同。如果用户输入了折扣代码,则可能会有所不同;如果指定的项目可以 不能按照所选的运输方式运输;当这些可能的条件彼此相交时,最终可能会出现几何数量不断增加的可能上下文。在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样式框架之间的第二个主要区别是断言(或“ matcher”)语法,只是使规范的样式更好。有些人真的喜欢,其他人则不喜欢。

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

  • 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。因为苹果当时(当时)即将宣布UIAutomation,所以我们特别决定不尝试让Cedar支持这些类型的规范。


感谢您的全面答复。我将阅读RSpec书并尝试Ceder。我将UISpec移至Selenium部分,并在那里也添加了UIAutomation。我正在阅读您关于UIAutomation的博客文章。弗兰克实际上看起来更简单,更易读,而且文件记载得更好,所以我考虑从此开始。我只是希望它像UIAutomation一样强大。您说UIAutomation可以测试生命周期问题。我想知道iCuke是否也可以...
ma11hew28 2011年

8

我将不得不把Frank扔进验收测试组合中。这是一个相当新的功能,但到目前为止对我来说效果非常好。此外,与icuke和其他公司不同,它实际上正在积极地进行研究。



4

很棒的清单!

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

西葫芦框架

它基于UIAutomation。该框架可让您以类似黄瓜的风格编写以屏幕为中心的场景。可以在控制台中的模拟器中和设备上执行方案(CI友好)。

断言基于屏幕截图。听起来不灵活,但是它可以为您提供出色的HTML报告,并具有突出显示的屏幕比较功能,并且您可以提供遮罩,以定义要精确定义像素的区域。

必须描述每个屏幕,CoffeScript并使用红宝石编写其本身的工具。这是种多语言的噩梦,但是该工具为UIAutomation屏幕提供了一个很好的抽象,当描述了屏幕时,它甚至对于QA人员也是可管理的。


紧!谢谢。我将此添加到上面的问题。
ma11hew28 2012年

2

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


1

GHUnit非常适合单元测试;对于集成测试,我已经成功使用了UISpec(github叉在这里:https//github.com/drync/UISpec),但是我期待尝试iCuke,因为它有望成为轻量级的安装程序,您可以使用RSpec和Cucumber之类的Rails测试良好性。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.