3

次のような Kiwi 仕様ファイルがあります。

#import "Kiwi.h"
#import "MyCollection.h"

SPEC_BEGIN(CollectionSpec)

describe(@"Collection starting with no objects", ^{
    MyCollection *collection = [MyCollection new];

    context(@"then adding 1 object", ^{
        MyObject *object = [MyObject new];
        [collection addObject:object];
        it(@"has 1 object", ^{
            [collection shouldNotBeNil];
            [collection.objects shouldNotBeNil];
            [[theValue(collection.objects.count) should] equal:theValue(1)]; //failing test
        });

        context(@"then removing 1 object", ^{
            [collection removeObject:object];
            it(@"has 0 objects", ^{
                [[theValue(collection.objects.count) should] equal:theValue(0)]; //passing test
            });
        });
    });
});

SPEC_END

spec を実行すると、このコード行で 1 つのエラーが発生します[[theValue(collection.objects.count) should] equal:theValue(1)];

context(@"then removing 1 object", ^{...})ここに奇妙な部分があります -仕様からブロック全体を削除すると、前述のテストに合格します。

[collection removeObject:object]これにより、失敗したテストの前に行が実行されていると私は信じています。ブロックが実行される順序を誤解している可能性があると感じています。

任意の提案をいただければ幸いです!

4

1 に答える 1

10

[collection removeObject:object]失敗したテストの前に実行されているのは正しいです。Kiwi テストは、次の 2 つのパスで動作すると考えてください。

  1. セットアップ: テスト ファイル内のコードが上から下に実行され、テスト コンテキストと期待値がセットアップされます。
  2. 実行: 各単体テストは基本的にit/specifyステートメントごとに 1 回実行され、各テストで正しいセットアップ/ティアダウン コードが繰り返されます。

Kiwi テスト ファイルのほとんどのコードは、Kiwi 関数に送信される一連のブロックとして指定されていることに注意してください。したがって、変数を初期化/変更するコードなど、Kiwi ブロック パターンに従わないコードはcollection、予期しない時間に実行される可能性があります。この場合、コレクションの変更コードはすべて、テストをセットアップする際の最初のパスで実行され、その後、テストが実行されます。

解決

修飾子を使用して宣言collectionし、オブジェクトのインスタンス化と変更に使用します。__blockbeforeEachcollection

describe(@"Collection starting with no objects", ^{
    __block MyCollection *collection;
    beforeEach(^{
        collection = [MyCollection new];
    });

    context(@"then adding 1 object", ^{
        beforeEach(^{
            MyObject *object = [MyObject new];
            [collection addObject:object];
        });
        it(@"has 1 object", ^{
            ...
        });

        context(@"then removing 1 object", ^{
            beforeEach(^{
                [collection removeObject:object];
            });
            it(@"has 0 objects", ^{
                ...

beforeEachブロックは、指定されたコードを単体テストごとに 1 回実行するように Kiwi に指示します。ネストされたコンテキストを使用すると、ブロックは必要に応じて順番に実行されます。したがって、キウイは次のようにします。

// run beforeEach "Collection starting with no objects"
collection = [MyCollection new]
// run beforeEach "then adding 1 object"
MyObject *object = [MyObject new]
[collection addObject:object]
// execute test "has 1 object"
[collection shouldNotBeNil]
[collection.objects shouldNotBeNil]
[[theValue(collection.objects.count) should] equal:theValue(1)]

// run beforeEach "Collection starting with no objects"
collection = [MyCollection new]
// run beforeEach "then adding 1 object"
MyObject *object = [MyObject new]
[collection addObject:object]
// run beforeEach "then removing 1 object"
[collection removeObject:object]
// execute test "has 0 objects"
[[theValue(collection.objects.count) should] equal:theValue(0)]

__block修飾子は、これらすべてのブロック機能を通じて、オブジェクトcollection参照を適切に保持および変更できるようにします。

于 2013-04-14T22:50:54.473 に答える