2017-08-15 8 views
8

を変更した場合、どのようにユニットテストの私はC++でこのクラスを持っているとしましょう:プライベート変数が

class ExampleClass{ 
private: 
    int example_var; 
public: 
    void exampleMethod(){ 
     example_var = other_value; // other value will be always different 
    } 
} 

をどのようにすることができますIユニットテストexampleMethod()

void testExampleMethod(){ 
    ExampleClass obj; 
    int before_call_value = obj.example_var; 
    obj.exampleMethod(); 
    int after_call_value = obj.example_var; 
    ASSERT_NOT_EQUALS(before_call_value, after_call_value); 
} 

しかしexample_varプライベートです:私はこのような何かをしたいと思います。

このユニットテストを行う正しい方法は何ですか?プライベートexample_varが変更された場合はどうすればテストできますか?

+1

'example_var'に対して' get'関数を実装していますか? –

+2

ユニットテストでは本当に主観的ですか?パブリックインターフェイスの動作?私は、ホワイトボックステストがその努力に値するとは確信していません。 – user0042

+0

By変数の変更、ユニットテスターとの友人関係の変更、または好みの順にゲッターを追加することで観察可能な振る舞いをテストします。 – user4581301

答えて

10

短い回答:しないでください。

あなたのテストはパブリックインターフェイスに対してのみテストする必要があります。私はいくつかのコードで説明してみましょう:

class Adder { 
    int a,b; 
public: 
    Adder() : a(0),b(0) {} 
    void set(int x,int y) { a=x;b=y; } 
    int get()    { return a+b; } 
}; 

とテスト(私たちはabへのアクセスを持っていた瞬間を仮定):

void testAdder(){ 
    Adder add; 
    int a = 1; 
    int b = 2; 
    add.set(a,b); 
    ASSERT_EQUALS(add.a,a); 
    ASSERT_EQUALS(add.b,b); 
    ASSERT_EQUALS(add.get(),a+b); 
} 

は、すでにコードを配布し、誰かが使用していると仮定それ。彼はそれを使い続けたいが、あまりにも多くのメモリ消費について不平を言う。同じパブリックインターフェイス維持しながら、この問題を修正するために簡単です。簡単だった

class Adder { 
    int c; 
public: 
    Adder() : c(0) {} 
    void set(int x,int y) { c = x+y; } 
    int get()    { return c; } 
}; 

を、しかしテストは

結論:(失敗します:テストのプライベート実装の詳細は、各ので、テストの目的に反しコードを変更するときには、テストを「修正する」必要がある可能性があります。

2

example_valにアクセスするには、2つの方法があります。

一方
class ExampleClass{ 
private: 
    int example_var; 
public: 
    void exampleMethod(){ 
     example_var = other_value; // other value will be always different 
    } 
    friend void testExampleMethod(); //Now you can use the function as is. 
} 

、あなただけの、次のような変数にアクセスするためにあなたのExampleClassにゲッターを追加することができます::

class ExampleClass{ 
private: 
    int example_var; 
public: 
    void exampleMethod(){ 
     example_var = other_value; // other value will be always different 
    } 
    inline void getExampleVar() const { return example_var; } 
} 
次のように最初は、 testExampleMethod()友人の方法を行うことです

そしてにtestExampleMethod()を変更します。クラスのプライベート変数へのアクセスは世代ですので、私は正直に、第二の方法を使用することになり

void testExampleMethod(){ 
    ExampleClass obj; 
    int before_call_value = obj.getExampleVar(); 
    obj.exampleMethod(); 
    int after_call_value = obj.getExampleVar(); 
    ASSERT_NOT_EQUALS(before_call_value, after_call_value); 
} 

ちょっとおすすめです。

4

私的変数/メソッドをテストするのは悪いアプローチです。あなたが必要な場合でも、多くのオプションがあります。

  1. 、あなたが単にMOCオブジェクトに

2

を使用して情報をつかむことができるでExampleClass

の友人
  • としてあなたのテストクラスを作ることができますそのprivate変数にget関数を実装してください。

    class ExampleClass{ 
    private: 
        int example_var; 
    public: 
        void exampleMethod(){ 
         example_var = other_value; // other value will be always different 
        } 
    
        int GetExampleVar(){ 
         return example_var; 
        } 
    } 
    

    そして

    void testExampleMethod(){ 
        ExampleClass obj; 
        int before_call_value = obj.GetExampleVar(); 
        obj.exampleMethod(); 
        int after_call_value = obj.GetExampleVar(); 
        ASSERT_NOT_EQUALS(before_call_value, after_call_value); 
    } 
    

    のようにそれを呼び出すか(でもそのないその方法ならばフレンドクラスのプライベート変数にアクセスすることができ、フレンド機能)testExampleMethodfriend functionを作ります。私の意見最初の例で


    class ExampleClass{ 
    private: 
        int example_var; 
    public: 
        void exampleMethod(){ 
         example_var = other_value; // other value will be always different 
        } 
    
        friend void testExampleMethod(); 
    } 
    

    がより適しているであろうが、あなたはExampleClassを変更できない場合、あなたはgccに対するアクセス制御をオフにすることができます - -fno-access-control

  • +2

    getterを追加するとパブリックAPIが変更されます。以前は隠されていたし、正当な理由で隠されていたかもしれない。 –

    +0

    確かにその1つのopputurnity。状態を隠しておく必要がある場合、彼は別のものを選ぶでしょう。 –

    2

    私は考えることができるいくつかのオプション:

    1)は、テストコードクラスのfriendください。そうすれば、プライベートメンバーにアクセスできます。

    2)のみのテストバージョンを構築するときに定義された(またはそのマクロの下public:を入れます#ifdef Testingディレクティブと#elseブランチのprivate:)下のクラスにゲッターを追加します。

    3)#define private publicテストをビルドするとき(いいえ、実際はありません)。

    4)テストするバージョンをビルドするときにgccの-fno-access-controlフラグを使用して、すべてが公開されるようにします(gccを使用している場合)。

    5)クラスから外部的にテストを放棄し、その代わりに不変量をテストするために、クラス自体に関連するstatic_assert s/assertを追加します。

    6)しないでください。パブリックインターフェイスをテストするだけです。

    希望に役立つ:-)

    関連する問題