読者です 読者をやめる 読者になる 読者になる

酔いどれエンジニアのブログ

有限会社wisdomのスタッフブログです。主にプログラミングやアプリケーション開発の話題を書いていきます。

Mac OS Xアプリを開発するためのBDDフレームワーク、Spectaを触る

iOS用はcalabash-iosKiwiなどがあるんですが、OS Xで使えるのはSpectaしか見当たらなかったので、とりあえず使ってみることに。

CocoaPodsが必要

Setupの項目を見たところCocoaPodsとやらが必要な様子。 これが何かというと、ライブラリ依存関係管理ツールの様子。 これに必要なライブラリを書けば、勝手に取ってきてくれるっぽい。 Rubyで作られたライブラリなので、動かすにもRubyが入っている必要があります。

作業

CocoaPodsをインストール

インストールする。

gem install cocoapods

デフォルトで用意されているライブラリの情報を~/.cocoapods/以下に準備するために以下のコマンドを実行する。

pod setup

Spectaをプロジェクトで利用できるようにする

対象のプロジェクトのホームディレクトリ(プロジェクト名.xcodeprojが存在するディレクトリ)に、Podfileという名前のファイルを作成する。

Podfileを以下のように記述する。

platform :osx

xcodeproj 'プロジェクトファイル名'

target :テストフォルダ名(○○○Tests) do
  pod 'Specta', '~> 0.1.11'
end

以下のコマンドを実行しライブラリをインストールする。 (Pods)というディレクトリができる。

pod install

以下のような警告が出るが無視しても良いみたい。

[!] The target `○○○` overrides the `FRAMEWORK_SEARCH_PATHS` build setting defined in `Pods/Pods-○○○.xcconfig'.
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.

確認する

.xcworkspaceファイルが出来ているので、これを開く。

○○○Tests内に、とりあえずSpectaTest.mというファイルを作り、GitHubにあるコードに適当にLog出力をつけて「Test」実行してみる 具体的には以下のような感じ。

#import <Foundation/Foundation.h>
#import <Specta/Specta.h>

SharedExamplesBegin(SpectaTest)
// Global shared examples are shared across all spec files.

sharedExamplesFor(@"a shared behavior", ^(NSDictionary *data) {
    it(@"should do some stuff", ^{
        id obj = [data objectForKey:@"key"];
        // ...
    });
    NSLog(@"sharedExamplesFor");
});

SharedExamplesEnd

SpecBegin(Thing)

describe(@"Thing", ^{
    sharedExamplesFor(@"another shared behavior", ^(NSDictionary *data) {
        // Locally defined shared examples can override global shared examples within its scope.
        NSLog(@"describe");
    });
    
    beforeAll(^{
        // This is run once and only once before all of the examples
        // in this group and before any beforeEach blocks.
        NSLog(@"beforeAll");
    });
    
    beforeEach(^{
        // This is run before each example.
        NSLog(@"beforeEach");
    });
    
    it(@"should do stuff", ^{
        // This is an example block. Place your assertions here.
        NSLog(@"should do stuff");
    });
    
    it(@"should do some stuff asynchronously", ^AsyncBlock {
        // Async example blocks need to invoke done() callback.
        done();
        NSLog(@"should do some stuff asynchronously");
    });
    // You'll have to build your project with Clang (Apple LLVM Compiler) in order to use this feature.
    
    itShouldBehaveLike(@"a shared behavior", [NSDictionary dictionaryWithObjectsAndKeys:@"obj", @"key", nil]);
    
    itShouldBehaveLike(@"another shared behavior", ^{
        // Use a block that returns a dictionary if you need the context to be evaluated lazily,
        // e.g. to use an object prepared in a beforeEach block.
        NSLog(@"another shared behavior");
        return [NSDictionary dictionaryWithObjectsAndKeys:@"obj", @"key", nil];
    });
    
    describe(@"Nested examples", ^{
        it(@"should do even more stuff", ^{
            // ...
        });
        NSLog(@"Nested examples");
    });
    
    pending(@"pending example");
    
    pending(@"another pending example", ^{
        // ...
        NSLog(@"another pending example");
    });
    
    afterEach(^{
        // This is run after each example.
        NSLog(@"afterEach");
    });
    
    afterAll(^{
        // This is run once and only once after all of the examples
        // in this group and after any afterEach blocks.
        NSLog(@"afterAll");
    });
});

SpecEnd

そうすると以下のようにログが表示された。 (Sandbox2は今回作ったプロジェクト名) 実行はされるようになった。

2013-09-09 18:39:54.908 Sandbox2[00000:000] sharedExamplesFor
2013-09-09 18:39:54.908 Sandbox2[00000:000] describe
2013-09-09 18:39:54.909 Sandbox2[00000:000] Nested examples
Running 7 tests:

F2013-09-09 18:39:54.931 Sandbox2[00000:000] beforeAll
2013-09-09 18:39:54.940 Sandbox2[00000:000] beforeEach
2013-09-09 18:39:54.940 Sandbox2[00000:000] should do stuff
2013-09-09 18:39:54.940 Sandbox2[00000:000] afterEach
.2013-09-09 18:39:54.945 Sandbox2[00000:000] beforeEach
2013-09-09 18:39:54.946 Sandbox2[00000:000] should do some stuff asynchronously
2013-09-09 18:39:54.946 Sandbox2[00000:000] afterEach
.2013-09-09 18:39:54.947 Sandbox2[00000:000] beforeEach
2013-09-09 18:39:54.947 Sandbox2[00000:000] afterEach
.2013-09-09 18:39:54.948 Sandbox2[00000:000] beforeEach
2013-09-09 18:39:54.949 Sandbox2[00000:000] afterEach