3

C++ では、クラス コンストラクターをどのようにテストしますか? 例えば:

Class myClass{
    int a;

public:
    myClass(); //Constructor
    void reset(); //resets a to 0;

};

//Constructor defined to initialize a to 0
myClass::myClass(){
    reset();
}

//reset sets a to 0
void myClass::reset(){
    a = 0;
}

myClass() コンストラクターをテストするにはどうすればよいですか? プライベート データ メンバーにアクセスできないので、リセットが機能する場合、コンストラクターが機能すると言うのは有効でしょうか?

4

4 に答える 4

9

私はあなたの質問を次のように言い換えます:保護されているかプライベートであるためにテストから直接観察できないクラスのプロパティをテストするにはどうすればよいですか?これが私が通常それらについて考える順序でいくつかの可能性です:

  • assert()を使用して、テストのチェック部分をクラスに移動します。テストしたいのが、コンストラクターがいくつかの複雑な不変条件を正常に確立したことである場合、その不変条件を検証するassert()をコンストラクターの最後に置くことができます。次に、テストで行う必要があるのは、コンストラクターを呼び出すことだけです。コンストラクター内のassertは、テストが実行したはずの実際のチェックを実行します。コードを作成するときにアサーションを習慣的に追加すると、そのアサーションはすでに存在します(アサーションによってデバッグビルドが遅くなりすぎる場合は、プロファイラーを使用して、実際に問題となっているアサーションを特定します)。

  • テストする複雑なコードを2番目のクラスに抽出します。次に、パブリックインターフェイスを介して2番目のクラスをテストできます。このオプションは、2番目のクラスを抽出するときに、テスト容易性を考慮しない場合でもコードを改善する場合に魅力的です。

  • コードの設計を、他の方法でよりテスト可能なものに変更します。繰り返しになりますが、これは、テスト容易性を考慮しなくても、変更が改善である場合に魅力的です。

  • 戦略的な撤退。コードを分離してテストすることは、他のすべての条件が同じであることは良いことですが、すべてのコードが同じでなければならないという法律はありません。単独でテストされます。正しい答えは、他の何かをテストすることの副作用として、そのコードをテストさせることです。結局のところ、そのクラスの他のすべてのテストはコンストラクターを呼び出すため、コンストラクターに問題があると、他のテストの1つが失敗する可能性があります。この方法ですべてのパスをカバーするのは難しいかもしれません。その障害が発生した時点では、問題がコンストラクターなのか他のテスト対象なのかわからないため、障害の原因を突き止めるのがさらに困難になります。 。それは大したことかもしれないし、そうでないかもしれない。このコードを単独でテストすることは本当に面倒な価値がありますか?そのときに他に何を使用できるか、そしてこのテストで実際にバグが見つかる可能性を考慮に入れますか?コードレビューは、その時間を過ごすためのより便利な方法でしょうか?他にもっと便利なことはありますか?

assert()でテストできないものを本当にテストする必要があり、テスト容易性を向上させるための許容可能なリファクタリングがない場合でも、いくつかのオプションがあります。これらをテストに使用する必要はありませんでしたが、次のとおりです。

  • フレンド宣言を使用して、テストにクラスのプライベートフィールドへのアクセスを許可します。各クラスは、アクセスが必要なテストのフレンド宣言のリストを維持する必要があります。これは維持するのが面倒な場合があります。

  • テストで使用するための個別のインターフェースを維持します。必要なアクセスを提供し、名前に「testOnly」のようなプレフィックスが付いた一連のメソッドを用意します。したがって、あなたの場合はtestOnlyGetA()になります。テストからこれらのメソッドを呼び出すだけで訓練を受ける必要があり、以前よりも大きなインターフェースを維持する必要があります。

  • テストするヘッダーを含める前に、鼻を押さえ#define private publicてテストファイルで実行します。

于 2012-11-19T16:31:41.280 に答える
0

更新。すみません、誤解しました。

フレンド テスト関数をクラスまたはクラス メンバー テスト関数に追加することができます (実装の詳細をテストするのに適していますが、テスト フレームワークの制限のために不可能な場合もあります)。

于 2012-11-19T05:26:50.320 に答える
0

クラスにブースト テスト ケースを追加できます。

Class myClass{
    private:
        int a;

    public:
        myClass(); //Constructor
        void reset(); //resets a to 0;
        void test_a_reset() {
            BOOST_CHECK_EQUAL(a, 0);
        }

};

ただし、テストをどのように行っているかはわかりません。これはあなたが望むものではないかもしれません。

于 2012-11-19T05:44:03.097 に答える
-1

元のクラスと同じメモリ レイアウトでテスト クラスを宣言できますが、すべてのメンバーは public です。

void testMyClassConstructor()
{
    class myClassPublic
    {
    public:
        int a;
        myClassPublic();
        void reset();
    };

    typedef union
    {
        myClass* original;
        myClassPublic* testView;
    } u_myClass;

    myClass testInstance;
    u_myClass testUnion;
    testUnion.original = &testInstance;

    assert(testUnion.testView->a == 0);
}

テスト対象のクラスのインターフェイスを変更できない場合、ホワイト ボックス テスト ケースではこれで問題ありません。ただし、元のクラスのメモリ レイアウトを変更すると、単体テストも中断されることに注意してください。

于 2012-11-19T14:44:38.663 に答える