Objective-C 中的 BDD

发布于 2024-08-02 10:38:00 字数 166 浏览 3 评论 0原文

我最近开始学习 Objective-C 并使用 Xcode 附带的 OCUnit 编写测试。

我是一名长期的 Ruby 程序员,我已经习惯了 RSpec 和 Cucumber——不错的 BDD 框架。

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

I have recently started to learn Objective-C and write my tests using OCUnit that comes bundled with Xcode.

I'm a long time Ruby programmer and I'm used to RSpec and Cucumber - nice BDD frameworks.

Is there a decent BDD framework to use in Objective-C? I'm missing my 'should's :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

满栀 2024-08-09 10:38:01

看一下 OCUnit(SenTestingKit,包含在 Xcode 中)中的 STAssert 宏是如何实现的。

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

如果您不太熟悉 C 预处理器...

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

@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。失败将正确显示在“构建结果”窗口中,单击它将带您到测试中失败的确切位置。

Take a look at how the STAssert macros in OCUnit (SenTestingKit, included with Xcode) are implemented.

In your own unit test bundle, you could implement a category on NSObject to add methods like a hypothetical -shouldBeValid which would then call the same pass/fail machinery that the STAssert macros do now.

In case you're not intimately familiar with the C preprocessor...

You'll probably also have to use a #define for your macros to pass through the right values for __FILE__ and __LINE__ when your BDD tests fail. For example, you might have to do something like this:

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

#define shouldBeValid  shouldBeValidInFile:__FILE__ line:__LINE__

That way you would invoke it like this:

[[someObject methodUnderTest:argument] shouldBeValid];

The code the compiler sees will be this:

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

The __FILE__ and __LINE__ preprocessor macros will expand to the current file and line in your test source file.

This way, when you do have a failing test, it can pass appropriate information to SenTestingKit to send back to Xcode. The failure will show up correctly in the Build Results window, and clicking it will take you to the exact location of the failure in your tests.

﹏雨一样淡蓝的深情 2024-08-09 10:38:01

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

You can take a look at BDD From the idea to the app where you'll see an example using calabash.

把梦留给海 2024-08-09 10:38:01

没有什么可以阻止您在测试方法前加上 Should 前缀。我用 C# 中的 NUnit 做到了这一点。

There is nothing stopping you prefixing your test method with Should. I did that with NUnit in C#.

独行侠 2024-08-09 10:38:00

我正在使用 Kiwi Library 集成速度很快,效果很好。

来自 他们的 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];
        });
    });
});

I'm using Kiwi Library Quick to integrate, works pretty well.

From their 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];
        });
    });
});
海的爱人是光 2024-08-09 10:38:00

有一个名为 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:@"[email protected]"];
  [[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

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

There's a relatively new project called uispec which was inspired by RSpec's testing DSL. The example spec looks like this:

#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:@"[email protected]"];
  [[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

Keep in mind that I've never used it, so there's a chance it won't fit your needs exactly. But at the very least, you'll be able to use the codebase as inspiration for writing your own test framework.

浅紫色的梦幻 2024-08-09 10:38:00

Pivotal Labs 的 Adam Milligan 为 Objective-C 创建了一个名为 Cedar 的 Objective-C 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

Adam Milligan of Pivotal Labs has created a BDD framework for Objective-C called Cedar that targets both Cocoa and Cocoa Touch. It uses blocks in a similar way to RSpec. Here's an example specification:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文