28

我最近开始学习 Objective-C 并使用与 Xcode 捆绑在一起的 OCUnit 编写我的测试。

我是一名长期的 Ruby 程序员,而且我习惯于 RSpec 和 Cucumber - 不错的 BDD 框架。

在 Objective-C 中是否有一个像样的 BDD 框架?我错过了我的“应该”:)

4

6 回答 6

21

我正在使用Kiwi Library Quick 进行集成,效果很好。

他们的github

describe(@"Team", ^{
    context(@"when newly created", ^{
        it(@"should have a name", ^{
            id team = [Team team];
            [[team.name should] equal:@"Black Hawks"];
        });

        it(@"should have 11 players", ^{
            id team = [Team team];
            [[[team should] have:11] players];
        });
    });
});
于 2011-01-28T11:40:13.123 回答
17

有一个相对较新的项目叫做uispec,它的灵感来自于 RSpec 的测试 DSL。示例规范如下所示:

#import "DescribeEmployeeAdmin.h"
#import "SpecHelper.h"

@implementation DescribeEmployeeAdmin

-(void)before {
  //login as default admin before each example
  [SpecHelper loginAsAdmin];
}

-(void)after {
  //logout after each example
  [SpecHelper logout];
}

-(void)itShouldHaveDefaultUsers {
  //Check that all default users are in list
  [[app.tableView.label text:@"Larry Stooge"] should].exist;
  [[app.tableView.label text:@"Curly Stooge"] should].exist;
  [[app.tableView.label text:@"Moe Stooge"] should].exist;
}

-(void)itShouldAddAUser {
  //Click the + button
  [app.navigationButton touch];

  //Set the form fields.
  //Also ".with" is optional so we here we can show the different syntax
  [[app.textField.with placeholder:@"First Name"] setText:@"Brian"];
  [[app.textField.with placeholder:@"Last Name"] setText:@"Knorr"];
  [[app.textField.with placeholder:@"Email"] setText:@"b@g.com"];
  [[app.textField placeholder:@"Username"] setText:@"bkuser"];
  [[app.textField placeholder:@"Password"] setText:@"test"];
  [[app.textField placeholder:@"Confirm"] setText:@"test"];

  //Click the Save button
  [[app.navigationButton.label text:@"Save"] touch];

  //Make sure the error alert view doesn't appear
  [app timeout:1].alertView.should.not.exist;

  //User list should now have a new entry
  [[app.tableView.label text:@"Brian Knorr"] should].exist;
}

@end

请记住,我从未使用过它,因此它可能无法完全满足您的需求。但至少,您将能够使用代码库作为编写您自己的测试框架的灵感。

于 2009-08-23T23:42:33.317 回答
14

Pivotal Labs 的 Adam Milligan 为 Objective-C 创建了一个名为Cedar的 BDD 框架,该框架同时针对 Cocoa 和 Cocoa Touch。它以与 RSpec 类似的方式使用块。这是一个示例规范:

SPEC_BEGIN(FooSpecs)

sharedExamplesFor(@"a similarly-behaving thing", ^(NSDictionary *context) {
    it(@"should do something common", ^{
        ...
    });
});

NSDictionary *context = [NSDictionary dictionary];

describe(@"Something that shares behavior", ^{
    itShouldBehaveLike(@"a similarly-behaving thing", context);
});

describe(@"Something else that shares behavior", ^{
    itShouldBehaveLike(@"a similarly-behaving thing", context);
});

SPEC_END
于 2010-07-06T17:40:51.183 回答
8

看看STAssertOCUnit(SenTestingKit,包含在 Xcode 中)中的宏是如何实现的。

在您自己的单元测试包中,您可以实现一个类别NSObject来添加方法,如假设,然后调用与宏现在所做-shouldBeValid的相同的通过/失败机制。STAssert

如果您对 C 预处理器不是很熟悉...

当 BDD 测试失败时,您可能还必须#define为宏使用 a 来传递正确的值。例如,您可能必须执行以下操作:__FILE____LINE__

@interface NSObject (BehaviorDrivenDevelopment)
- (void)shouldBeValidInFile:(const char *)file line:(int)line;
@end

#define shouldBeValid  shouldBeValidInFile:__FILE__ line:__LINE__

这样你就可以像这样调用它:

[[someObject methodUnderTest:argument] shouldBeValid];

编译器看到的代码是这样的:

[[someObject methodUnderTest:argument] shouldBeValidInFile:__FILE__ line:__LINE__];

__FILE__和预__LINE__处理器宏将扩展到测试源文件中的当前文件和行。

这样,当您确实有一个失败的测试时,它可以将适当的信息传递给 SenTestingKit 以发送回 Xcode。失败将正确显示在“构建结果”窗口中,单击它将带您到测试中失败的确切位置。

于 2009-08-23T23:17:53.930 回答
3

您可以查看BDD 从想法到应用程序,您将在其中看到使用葫芦的示例。

于 2012-11-16T11:00:23.157 回答
0

没有什么能阻止你在测试方法前加上 Should。我在 C# 中使用 NUnit 做到了这一点。

于 2009-08-23T13:19:12.117 回答