Catch使用マニュアル

9219 ワード

キャッチを取得
Catchを取得する最も簡単な方法は、最新のシングルヘッダファイルバージョンをダウンロードすることです.このファイルは、個別のヘッダファイルのセットをマージすることによって生成されますが、通常のソースコードを含むヘッダファイルにすぎません.Catchの完全なソースコードは、テスト項目、ドキュメント、その他の内容を含め、GitHubが管理しています.http://catch-lib.netリダイレクトします.
どこに置きますか.
Catchにはヘッダファイルが1つしか必要ありません.必要なのは、指定したサードパーティ製ライブラリの場所にファイルを配置し、ヘッダーファイル検索パス(VS下のC++ディレクトリ->ディレクトリを含む)で検索するか、プロジェクト内でディレクトリツリーを介して直接配置するか、プロジェクトにファイルを含めることです.Catchのテストキットを使用したい他のオープンソースプロジェクトにとって、これは特に良い選択です.詳細については、ブログエントリを参照してください.このチュートリアルの残りの部分では、単一ヘッダファイルのCatchを直接使用します.もちろん、フォルダに置いて使用することもできます.
テストケースの作成
簡単な例でCatchの使い方を説明します.階乗を計算する方法を書く必要があるとしたら、それをテストします(まずテスト駆動開発の問題を気にしないでください).
unsigned int Factorial( unsigned int number ) {
    return number <= 1 ? number : Factorial(number-1)*number;
}

簡単にするために、すべてのコードを同じファイルに書きます(テストファイルをどのように組織するかについては、 )
#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"

unsigned int Factorial( unsigned int number ) {
    return number <= 1 ? number : Factorial(number-1)*number;
}

TEST_CASE( "Factorials are computed", "[factorial]" ) {
    REQUIRE( Factorial(1) == 1 );
    REQUIRE( Factorial(2) == 2 );
    REQUIRE( Factorial(3) == 6 );
    REQUIRE( Factorial(10) == 3628800 );
}

Let's add that to the test case:コマンドラインパラメータに応答する完全な実行可能ファイルにコンパイルされます.パラメータなしで実行すると、すべてのテスト・インスタンスが実行され、失敗が報告され、テストの合格と失敗の要約が報告され、失敗したテストの数が返されます.(どのようにあなたが望んでいるのは、「コードが正常に機能するかどうか」という答えだけです).
上記のテスト・インスタンスを実行すると、合格します.すべてがうまくいっています.そうですか.しかし、ここにバグがあります.問題はゼロの乗算とは何ですか.ゼロの乗算については、ここをクリックしてテスト・インスタンスを補足します.
TEST_CASE( "Factorials are computed", "[factorial]" ) {
    REQUIRE( Factorial(0) == 1 );
    REQUIRE( Factorial(1) == 1 );
    REQUIRE( Factorial(2) == 2 );
    REQUIRE( Factorial(3) == 6 );
    REQUIRE( Factorial(10) == 3628800 );
}

次のような失敗のヒントが得られます.
Example.cpp:9: FAILED:
  REQUIRE( Factorial(0) == 1 )
with expansion:
  0 == 1

印刷されたFactorial(0)の戻り値が0で、自然な==式が使用されていることがわかります.問題がどこにあるかを直感的に見るのに役立ちます.factorial関数のコードを変更します.
unsigned int Factorial( unsigned int number ) {
  return number > 1 ? Factorial(number-1)*number : 1;
}

すべてのテストに合格しました.もちろん、私たちができることはたくさんあります.例えば、unsigned intの値範囲を超えた値を返すと、私たちは問題に直面します.関数factorialsはこのようなことが起こりやすいです.このような状況のためにテストを増やし、どのように処理するかを決定する可能性があります.ここでは、このような問題を処理しません.
ここで私たちは何をしましたか?
これは簡単なテストですが、どのようにCatchするかを理解するのに十分です.続ける前に、時間をかけて振り返ってみましょう.
  • 私たちがしなければならないのは#define1つの識別が#include1つのヘッダファイルに合致し、それから私たちはすべてを持っていて、mainの実現さえコマンドラインパラメータに応答することによって完成します.あなたは1つのcppファイルの中で#defineしかできません.明らかな原因(翻訳速度)のためです.ユニットテストが必要なファイルが1つ以上ある場合は、各測定対象ファイルに#include "catch.hpp"が必要です.通常、専用のcppファイルに#define CATCH_CONFIG_MAIN#include "catch.hpp"が必要です.もちろん、自分のmain関数を実装し、自分で実行するCatchの機能も提供できます.(詳細は、自分のmain関数を提供します).
  • ここでは、TEST_CASEマクロを使用してテストの例を説明します.このマクロには、任意の文字列と1つ以上のラベル(詳細は、Test cases and Sectionsを参照)の1つまたは2つのパラメータがあります.を選択します.テスト・インスタンスの名前は一意でなければなりません.ワイルドカードを指定してテスト・インスタンス名またはラベル式を識別することで、指定したテスト・インスタンスを実行できます.テスト・インスタンスの実行の詳細については、コマンド・ライン・ドキュメントを参照してください.
  • テストケース名およびラベルは、通常の文字列にすぎません.これまでメソッドまたは関数を宣言したり、テストケースを任意の場所に明示的に登録したりしていません.バックグラウンドでは、テストケース名によって関数を定義し、静的レジストリクラスを使用して自動的に登録します.関数名を抽出することで、テストケースの名前を付けることができます.識別子名の制約を受けません.
  • マクロは、REQUIREマクロによって個別のテストブレークスルーを記述します.各条件に対して個別のマクロを定義するのではなく、自然なC/C++の意味を使用して条件を表現します.バックグラウンドでは、単純な表現テンプレートのセットが式の左側と右側をキャプチャし、テストレポートに値を表示できます.後で他のブレークスルーマクロが表示されますが、このため技術、それらの数量は急激に減少します.
  • テストケースとセクション
    ほとんどのテストフレームワークには、クラスベースのスイート・メカニズムがあります.つまり、テスト・インスタンスはクラスにマッピングされ、初期化および破棄はsetup()メソッドおよびteardown()メソッドで実行されます(C++などの言語では構造/プロファイルと呼ばれます)..Catchはこの動作を完全にサポートしていますが、いくつかの問題があります.特に、コードを分割する必要があり、その細粒度が問題になる可能性があります.一連の方法では、1対のsetup/teardown/setupしか使用できませんが、各関数でわずかに異なるNUnitを設定するか、複数のレベルの設定が必要になる場合があります.(このチュートリアルでは後述する).James Newkirkがチームを率いてNUnitを内蔵し、xUnitを最初から構築する.Catchは異なる方法(xUnitおよびSECTION)を採用しており、これはC++およびCシリーズの言語にとってより自然である.一例で完璧に解釈する:
    TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
    
        std::vector v( 5 );
        
        REQUIRE( v.size() == 5 );
        REQUIRE( v.capacity() >= 5 );
        
        SECTION( "resizing bigger changes size and capacity" ) {
            v.resize( 10 );
            
            REQUIRE( v.size() == 10 );
            REQUIRE( v.capacity() >= 10 );
        }
        SECTION( "resizing smaller changes size but not capacity" ) {
            v.resize( 0 );
            
            REQUIRE( v.size() == 0 );
            REQUIRE( v.capacity() >= 5 );
        }
        SECTION( "reserving bigger changes capacity but not size" ) {
            v.reserve( 10 );
            
            REQUIRE( v.size() == 5 );
            REQUIRE( v.capacity() >= 10 );
        }
        SECTION( "reserving smaller does not change size or capacity" ) {
            v.reserve( 0 );
            
            REQUIRE( v.size() == 5 );
            REQUIRE( v.capacity() >= 5 );
        }
    }
    

    We might want to verify that attempting to reserve a capacity smaller than the current capacity of the vector changes nothing.We can do that,naturally,like so:各TEST_CASEおよび各sectionについて最初から実行されています.したがって、各SECTIONに入ると、サイズは5であり、容量は少なくとも5であることがわかります.これは正常に動作します.マクロsectionにはif文が含まれているため、TEST_CASEを実行すべきかどうかを確認するためにCatchがコールバックされます(部分)を選択します.スタックを作成しました.しかし、一連の検査操作を実行する必要がある場合にのみ、sectionの実力が実際に表示されます.sectionの例を続行すると、sectionの容量が現在の容量より小さい場合、無効であることを検証したい場合があります.たとえば、次のようにします.
        SECTION( "reserving bigger changes capacity but not size" ) {
            v.reserve( 10 );
            
            REQUIRE( v.size() == 5 );
            REQUIRE( v.capacity() >= 10 );
        
            SECTION( "reserving smaller again does not change capacity" ) {
                v.reserve( 7 );
                
                REQUIRE( v.capacity() >= 10 );
            }
        }
    
    setupは任意の深さ(スタックサイズのみ)にネストすることができる.各リーフteardown(すなわち、ネストsetupを含まないsection)は、他のブレード部分を実行するための別のパス上で1回実行される(したがって、ブレード部分は他のリーフノードに干渉する可能性がある).親vectorの失敗は、ネストvectorの実行を阻止するように設計されている.
    BDDスタイル
    テスト・インスタンスとセクションの名前を適切に付けた場合は、BDDスタイルの仕様構造を実装できます.これは、Catchが適切なサポートを追加した有用な動作となります.シーンでは、指定したSections,section,section,sectionおよびsectionマクロを使用して、sectionおよびSCENARIOにマッピングできます.詳細は、Test cases and sectを参照してください.ions.GIVEN例は、以下に示すように、これらのマクロを使用するように調整することができる.
    SCENARIO( "vectors can be sized and resized", "[vector]" ) {
    
        GIVEN( "A vector with some items" ) {
            std::vector v( 5 );
            
            REQUIRE( v.size() == 5 );
            REQUIRE( v.capacity() >= 5 );
            
            WHEN( "the size is increased" ) {
                v.resize( 10 );
                
                THEN( "the size and capacity change" ) {
                    REQUIRE( v.size() == 10 );
                    REQUIRE( v.capacity() >= 10 );
                }
            }
            WHEN( "the size is reduced" ) {
                v.resize( 0 );
                
                THEN( "the size changes but not capacity" ) {
                    REQUIRE( v.size() == 0 );
                    REQUIRE( v.capacity() >= 5 );
                }
            }
            WHEN( "more capacity is reserved" ) {
                v.reserve( 10 );
                
                THEN( "the capacity changes but not the size" ) {
                    REQUIRE( v.size() == 5 );
                    REQUIRE( v.capacity() >= 10 );
                }
            }
            WHEN( "less capacity is reserved" ) {
                v.reserve( 0 );
                
                THEN( "neither size nor capacity are changed" ) {
                    REQUIRE( v.size() == 5 );
                    REQUIRE( v.capacity() >= 5 );
                }
            }
        }
    }
    

    これらのテストは、実行時に次のように報告されます.
    Scenario: vectors can be sized and resized
         Given: A vector with some items
          When: more capacity is reserved
          Then: the capacity changes but not the size
    

    さらに
    チュートリアルを簡略化するために、すべてのコードを1つのファイルに配置します.これによって開始するのは良いです.Catchにもっと速く、簡単に入ることができます.しかし、実際の世界のテストをもっと書くと、これは本当に最善の方法ではありません.このようなコードブロック(または等価物)を書きます.
    #define CATCH_CONFIG_MAIN
    #include "catch.hpp"
    

    ちょうど1つのソースファイルに表示されます.可能な限り多くの追加のcppファイル(インプリメンテーションファイルとも呼ばれます)を使用してテストを行います.ある意味、お客様の作業に最適です.これらのcppファイルはWHEN-繰り返しTHEN|を必要としません.実際には、指定したソースファイルにTEST_CASESを配置します.(このファイルにはSECTIONvectorの2つのコードしか含まれていません)通常は良いアイデアです.ヘッダーファイルにテストを書かないでください.
    次のステップ
    これは簡単な説明です.Catchを実行し始め、Catchとおなじみの他のフレームワークの主な違いを指摘します.これにより、遠くまで行くことができます.テストを深く理解し、書くことができます.もちろん、もっと勉強する必要があります.参考部分を参照して、使用可能な内容を理解してください.
    Catch公式サイト