Kiwi--BDDモードでのユニットテストの自動化

6386 ワード

Kiwi--BDDモードでのユニットテストの自動化


まずタイトルの中のBDDを見て、これは何の鬼ですか?ここでは、まず現在の異なるテスト思想を見てみましょう.

TDDとBD

  • 行動駆動開発(英語:Behavior-driven-development、略称BDD)は敏捷に開発された技術で、BDDはテスト文を自然言語のような記述に変換することで、開発者はより大衆言語に合った習慣を使ってテストを書くことができ、他の人が引き継いだり、自分で修正したりするとき、簡単で分かりやすく、順調にいくことを提唱している.1つの典型的なBDD試験例は完全な3段式コンテキストを含み、試験の多くはGiven...When...Thenのフォーマットに翻訳することができ、読みやすい.
  • テストドライバ開発(英語:Test-driven-development、略称TDD)は、ソフトウェア開発における応用方法であり、限界プログラミングによって提唱されている.TDD需要やインタフェースの状況に応じてテストを作成してから、テストに基づいてビジネスコードを作成することを提唱する.まず、これは従来のソフトウェア開発における先行認識、特に国内環境に違反している.しかし、TDDモードでは、コードの使用など、事前に深く考え、実践することで、設計と拡張性を高めることができます.また、テストの保護があるため、論理の破壊や論理の損失を心配することなく、既存のコードを安心して再構築することができます.

  • 上の2つのテスト思想の違いを見た後、私たちの現在のiOSと国内環境の下で、BBDテスト方法は私たちの第一選択だと思います.BDDは、Kiwiを紹介しなければなりません.

    Kiwi


    KiwiのGitHubアドレス:https://github.com/kiwi-bdd/Kiwi

    インストール方法

  • CocoaPodsでの取り付け
  • target :YourProjectTests do
        pod 'Kiwi';
    end
    

    ここで注意しなければならないYourProjectあなた自身のプロジェクト名です.
  • 手動導入
  • ダウンロードKiwiProjectシミュレータとGeneric iOS Deviceコンパイルを選択すると対応するKiwi.frameworkが生成されます.
  • 生成したものをKiwi.frameworkあなたの工事に引きずり込んで、注意、引きずり込んで、引用ではありません
  • test targetのsetting - Build Phases奥のLink Binary With Libraiesに追加
  • テストターゲットを設定するUser Headers Searchその位置を指す
  • テストターゲットの設定Runpath Search Paths、追加$(FRAMEWORK_SEARCH_PATHS)非常に重要で、そうでないとエラー
  • Other Linker Flagsに追加-ObjC.


  • Kiwiの基本文法と構造


    自分で書くKiwi文法を始める前に、Kiwiの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];
            });
        });
    });
    

    文脈で抽出できるGiven...When...Thenの三段式自然言語
    Given a team,when newly created,it should have a name,and should have 11 players
    
    describeテストが必要な対象内容を記述する、すなわち我々三段式中のGivencontext・テストの文脈を記述する、つまりこのテストはwhenで行われ、最後itのはテストの本体であり、このテストがどのような約束(条件)を満たすべきかを記述し、三者は共にKiwiテストにおける動作記述を構成する.これらはnest、つまり1つSpecファイルに複数含まれることができるdescribe(私たちはそうすることはめったにありませんが、1つのテストファイルは1つのクラスをテストすることに専念すべきです).1つdescribe複数のcontextを含むことができ、クラスの異なるシナリオでの動作を記述する.1個context複数含むことができるitの試験例.
    この例では、次のような重要な動作記述キーワードについて説明します.
  • Kiwi-現在のbeforeAll(aBlock)内部の全ての他scope運転前に一度呼び出す
  • block-現在afterAll(aBlock)内部全てscope運転後1回呼び出す
  • block-beforeEach(aBlock)内のitマネーごとに1回呼び出す、scopeの配置はこちら
  • context-alterEach(aBlock)内のitごとに1回呼び出し、テスト後のコードとクリア状態をクリア
  • scope-記述不要のテストを直接書くことができる
  • specify(aBlock)-1本のみ印刷pending(aString, aBlock)テストをしないというメッセージは、行動記述がまだ実現していないテストを集中的に書き始めるヒントとして警告されます
  • logxit(aString,aBlock)と同様、別の書き方.実装時にテスト時にxを削除するだけで済むのがpendingですがit意味がより明確なのでおすすめpending
  • pendingが存在し、ネスト可能な特性のため、テストのフロー制御は従来のテストよりも正確であることがわかる.context beforeの役割領域を適切な場所に制限しやすい.実際のテストはafterに書かれており、1つ1つの期待itによって記述されており、従来のテストでの断言に相当する期待があり、実行結果が期待に合致しなければテストに失敗する.(Expectations)中期望都ではKiwiまたはshouldから始まり、1つまたは複数の判断のチェーン呼び出しが続くが、ほとんどがshouldNotまたはbeの形式である.

    Kiwi使用例


    どのようにKiwiを利用してユニットテストを行いますか!私たちのプロジェクトにはhaveSomeConditionのクラスが追加されました
    @interface Person : NSObject
    - (CGFloat)everyDayTheBodyPutOnWeight:(CGFloat)weight;
    - (CGFloat)everyDayRunForKeepFitLoseWeight:(CGFloat)weight;
    
    @interface Person()
    @property (nonatomic, assign) CGFloat totalWeight;
    @end
    @implementation Person
    
    - (instancetype)init
    {
        if (self = [super init]) {
            _totalWeight = 50.0;
        }
        return self;
    }
    - (CGFloat)everyDayTheBodyPutOnWeight:(CGFloat)weight
    {
        return _totalWeight + weight;
    }
    
    - (CGFloat)everyDayRunForKeepFitLoseWeight:(CGFloat)weight
    {
        return _totalWeight - weight;
    }
    

    このクラスのユニットテストをkiwiで作成するにはどうすればいいですか?
    #import 
    #import "Person.h"
    
    SPEC_BEGIN(PersonSpec)
    describe(@"every one for a day", ^{
        
        context(@"for lose or put on weight", ^{
            
            __block Person *p = nil;
            beforeEach(^{
                p = [Person new];
            });
            afterEach(^{
                p = nil;
            });
            
            it(@"put on weight", ^{
                CGFloat onWeight = [p everyDayTheBodyPutOnWeight:7];
                [[theValue(onWeight) should] equal:57 withDelta:2];
            });
            
            it(@"lose weight", ^{
                CGFloat loseWeight = [p everyDayRunForKeepFitLoseWeight:10];
                [[theValue(loseWeight) should] beLessThanOrEqualTo:theValue(50)];
            });
            
        });
    });
    
    SPEC_END
    

    このテスト例をcommand+Uで実行すると、次のように出力されます.
    - 'every one for a day  when for lose or put on weight, put on weight' [PASSED]
    - 'every one for a day  when for lose or put on weight, lose weight' [PASSED]'
    

    以上の文法で用いられるPerson・を説明する.
    Kiwiは、theValueというスカラー変換対象の文法糖を提供しています.正確な比較をするときは、例の中で直接theValueまたは7と比較するような書き方で比較することができます.
    このような簡単な例を通して、基本的に10の簡単な文法とKiwiの使い方を身につけることができます.ユニットテストは入門の敷居が高くないにもかかわらず、どのように心を込めて、頭を働かせてユニットテストを書き、自動化を実現することができるかは、私たちのプログラマーにとって大きな試練です.さらにkiwiを使用するには、KiwiがステップMock、Stub、パラメータキャプチャ、非同期テストを使用していることを確認してください.

    まとめ:


    まず、CocoaPodsと緊密に結合し、公式にPodsを作成した後、Kiwiを生成するテストプロジェクトを直接サポートします.次に、そのBDDの特性のため、文法の可読性が強い.最後に、XCTestに基づいて開発されたので、XCodeのサポートはよく、直接XCodeでテスト回帰やデバッグを行えばよい.
    参考文献:
    TDDのiOS開発の初歩とKiwi使用の入門
    iOS開発——TDD、BDD方法及びKiwiユニットテストフレームワーク