9

単体テストの最初の一歩を踏み出しましたが、カプセル化に問題があります。私のクラスには、クライアントに表示されるべきではないいくつかのプライベート メンバー変数がありますが、オブジェクトをテストしたい状態にするために、それらのプライベート変数を設定する必要があります。

次のようなコードがあるとします。

Class Foo {

public:
  int action() ;  
private:
  int state ;

} ;

int Foo::action()
{
  if(this->state == 1)
    return 1 ;
  else
    return 0 ;
}

だから今私はテストしたいのですが、さまざまなシナリオで機能をチェックできるFoo::action()ように設定できる必要があります。1 つの解決策は、テスト コード内Foo::stateの悪" "です。define private publicしかし、もっとエレガントなものはありますか?これはクライアントがアクセスしてはならない変数であることを強調しFoo::stateたいので、パブリック セッターを宣言したくありません。

編集:

テスト コードでテストしたいクラスを拡張し、その派生クラスにセッターを含めれば、プライベート変数を保護変数に変更すれば機能すると思います。しかし、これは「1 世代のみ」のソリューションであり、適切なアプローチというよりもハックのように感じられます。

編集2:

私が与えられた回答とコメントを読んだ後 (特に Lieven と ap. に感謝します) 私が今テストしようとしている実際のクラス (私が提供した単純な例ではありません) は単純にやりすぎで、私の問題に対する答えは動いていると思いますそのロジックの一部を、大物が使用する別のクラスに変換します。

4

3 に答える 3

4

2つの可能性しかありません(リファクタリングは別として)

  1. パブリック インターフェイスを使用して状態を設定します。
  2. パブリック インターフェイスを介して設定できない場合、状態は冗長です。

オプション2は自明であり、おそらくあなたのケースには当てはまらないので、クラスのパブリックインターフェースを介して状態を設定する必要があります。

すでに述べたように、これは可能ですが、正しい状態にするには多くのコードが必要です。それ自体は、クラスが現在多くのことを行っていることを示している可能性があり、クラスの一部をリファクタリングして、より小さくテスト可能なクラスにする必要があります。

からプライベートメソッドをテストしないでください

プライベート メソッドをテストする必要があるとわかった場合は、別の方法が間違っています。いわば「上流」の問題があります。このプロセスの前に別のミスがあったため、この問題にたどり着きました。それが何であるかを正確に分離し、それを取り除くようにしてください.

プライベートメンバーの単体テスト

プライベート メソッドを単体テストしないことをお勧めします。それらは非公開であるため、リリースごとに考えられる (または考えられない?) 方法で変更される可能性があります。特定のプライベート メソッドがクラスの操作にとって非常に重要であり、テスト ケースに値すると思われる場合は、おそらくそれをプロテクト メソッドまたはパブリック メソッドにリファクタリングする時期です。

これに関する一般的な引用は

プライベートに触れてはいけない

于 2012-12-20T12:04:16.930 に答える
1

テスト クラスが MyTestClass という名前の場合、クラス Foo に MyTestClass をフレンドとして追加して、そのプライベート メンバー変数にアクセスできるようにします。

Class Foo {
public:
    int action();  
private:
    int state;

    friend class MyTestClass;
};
于 2012-12-20T12:44:28.413 に答える
1

プライベート変数の値を変更するには、ly (または "ly") アクセス可能なメカニズムが必要publicです。簡単にするために、それが method であるとしましょう。それを単体テストで使用して状態を変更し、メソッドをテストします。これにより、将来の実装の変更が単体テストに影響を与えないことが保証されます (「API」が変更されない限り、もちろん、単体テストを変更する必要があります)。protectedstateFoo::setState(int inState)Foo::action()Foo::setState()

を変更するそのようなメカニズムがない場合state、エンドユーザーまたは呼び出し元のコードもそれを変更できないことを意味するため、テストする必要はありません(おそらくそれはstate冗長になりますが、私はそれについて知りません)。

プライベート変数が他のコードを通じて「間接的に」変更された場合、単体テストで同じコードを実行する必要があります。外部からコードに供給された入力に対して、外部から見えるメソッドはいつでもトレースバックできます。基本的に重要なのは、単体テストでは、「実際の」シナリオと同じ入力をコードに供給し、それが適切に応答するかどうかをテストする必要があるということです。

以下のコメントで説明されているように、入力からテスト対象のコードまでの「パス」が長すぎる場合、コード/テストを小さなモジュールまたは中間点に分割する必要がある場合があります。詳細を説明するために、コード フローを次のように考えます。

Input -> A -> B -> C -> Output
// A, B, C are intermediate execution points which are not "publicly accessible".

上記の場合、できることは

が与えられた場合、が正しいInputかどうかを確認します。Output

代わりに、中間Aの , B,Cを少なくとも単体テストに公開して、テストを次のように分割できるようにすることをお勧めします。

が与えられた場合、が正しいInputかどうかを確認します。A

が与えられた場合、が正しいAかどうかを確認します。B

が与えられた場合、が正しいBかどうかを確認します。C

が与えられた場合、が正しいCかどうかを確認します。Output

ご想像のとおり、テストが失敗した場合、何が失敗したかを特定し、それを修正することが容易になります。

于 2012-12-20T12:46:27.567 に答える