web-dev-qa-db-ja.com

テスト用にプライベートなものを内部/パブリックにするか、PrivateObjectのようなハックを使用しますか?

私はコードテストの初心者で、以前はassertの売春婦でした。単体テストで私が心配していることの1つは、多くの場合public(または少なくともinternal)のフィールドをprivateにしないと、-readonlyを解除する必要があることです。それら、代わりにprivateメソッドprotected virtualなどを作成します...

PrivateObject クラスのようなものを使用して、リフレクションを介してオブジェクト内のすべてにアクセスすることで、これを回避できることを最近発見しました。しかし、これによりテストの保守性が低下します(コンパイル時ではなく実行時に問題が発生します。単純な名前変更によって壊れてしまい、デバッグが難しくなります...)。これについてどう思いますか?アクセス制限に関する単体テストのベストプラクティスは何ですか?

編集:たとえば、ディスク上のファイルにキャッシュを持つクラスがあり、テストでは代わりにメモリに書き込むことを検討してください。

28
Zonko

あなたは決してする必要はありません

それ以外の場合はpublicであったはずのinternal(または少なくともprivate)フィールドを作成し、readonlyを解除するには、privateメソッドを作成しますprotected virtual代わりに

特に、フィールドの読み取り専用を解除すると、不変オブジェクトが変更可能になる可能性があり、それは災害となります。

テストでは、オブジェクトをブラックボックスWikipedia )と見なす必要があります。つまり、オブジェクトは、オブジェクト。実装の詳細は含まれません。

パブリックインターフェイスを使用してオブジェクトを十分にテストできない場合は、テストを容易にする、そのインターフェイスに正式で便利な拡張機能を提供する方法を見つける必要があります。たとえば、登録/登録解除メソッドのペアのみを備えた登録システムは、手元のアプリケーションで必要ない場合でも、IsRegisteredメソッドの恩恵を受ける可能性があります。それでも、これはインターフェースの正式で便利な拡張であり、偶然にもテストに対応します。

重要なことは、オブジェクトの実装を変更しても、ユニットテストを変更する必要がないことです。理論的には、ユニットテストを1回記述し、複数のプログラマにユニットテストで動作するようにテストするオブジェクトの複数の完全に異なる実装をコーディングするように依頼することができます。

38
Mike Nakis

C#では、InternalsVisibleToAttributeを使用して、テストアセンブリがテスト中のアセンブリのinternalクラスを参照できるようにすることができます。もうご存知のようですね。

ほとんどの場合、私は自分のアセンブリのパブリックAPIのテストのみに関心があります。あるユニットのホワイトボックステストを行う場合は、コードをinternalクラスに移動し、そのクラスのpublicメソッドにします。次に、そのクラスの単体テストをコーディングできます。

これは、依存性注入と戦略パターンに適しています。メソッドをインターフェイスに抽象化し、そのインターフェイスを親オブジェクトのコンストラクターに注入して、親が適切に委譲することをテストするだけです。次に、子オブジェクトが適切に動作することをテストできます。これにより、すべてがよりモジュール化されます。

14
Scott Whitlock

私の経験では、特別にテストのためにクラスの内部を公開しないことが最善です。これは、テストを記述しやすくするために表示される場合があります。テストはクラスの最初のクライアントであるため、パブリックインターフェイスを介してクラスをテストするのが難しい場合、他の場所でもクラスを使用することはおそらく難しいでしょう。

クラスがそのパブリックAPIを介してテストするのがいかに簡単であるかは、クラスの使いやすさに関するフィードバックです。テストは、クラスの使用をプロトタイプ化する方法として部分的に考えてください。

テストで、パブリックAPIを介して利用できないクラスについて何かを検知する必要がある理由を検討してください。おそらく、あなたのクラスはあまりにも多くをやっていて、代わりに協力するクラスのグループに分解する必要があるでしょうか?次に、コラボレーションしているクラスの一部をモックして、テスト中のクラスが何をしているかを感知できます。

dependency inversion principal を適用して、テストでモックできるクラス間にインターフェースを導入してみてください。 制御の反転 を使用して、テストに協力者を提供できます。

"tell do n't ask" プリンシパルを適用して、適切な情報が公開され、残りが非表示になる堅牢で疎結合な方法でクラスインターフェイスを構築することも検討してください。

8
flamingpenguin

個人的には、テストしているコードをできる限り純粋なままにしておき、テストコードにハック(およびC++の厄介なポインターなど)が必要な場合は、喜んでそれを行います。

6
Ant

コードの可視性は単体テストとは関係ありません!

メソッドをテストから非表示にする目的ではなくプライベートにし、テスト用に公開するためにメソッドをパブリックにしませんか?これは、ここで不可欠な実装であり、テストではありません。コードの証明としてのサーバーではありますが、コードはコードではありませんです。

非表示(プライベートまたは内部)のメソッドとプロパティへのアクセスを有効にする方法はたくさんあります。多くのテストフレームワークとIDE(たとえば、Visual Studio)は、アクセスに必要なすべてを生成することにより、ここでサポートします。テストケースを作成するだけで済みます。では、なぜ心配するのでしょうか。コードをきれいに整理してください。

5