『Effective Unit Testing』読書ノート4テスト身代わり(Test Doubles)

3251 ワード

テストエージェントは、テストコードが接触する他のコードの代わりにコードを書くことです.まず答えなければならない質問は、なぜ身代わりをテストする必要があるのかということです.著者は以下の点を挙げた.
  • テストするコードを分離する
  • テストの実行を速める
  • 実行に確定性を持たせる
  • 特殊な条件
  • をシミュレートする
  • 非表示の情報
  • にアクセスする.
    次はそれぞれこの点を見てみましょう.テストするコードを分離します.これは、テストするコードとテストコードとインタラクティブなコードを明確に区別することを意味します.元のコードがうまく書けなかったり、最初からテスト向けではなかったりすると、実は隔離しにくいので、現実的にはテストコードは自分のコードの誤りではなく、コードに依存する誤りによって通じないことが多い.
    テストの実行を速める:これは理解しやすいが、私たちが実際に依存するコードを実行する論理(複雑なアルゴリズム、他のネットワークサービスへのアクセス、時間のかかるIOアクセスなどを含む可能性がある)を代替することによって、実際に実行する必要がない以上、テストは自然に速くなる.
    実行に決定性を持たせる:最も典型的な例は、現在のシステム時間に依存するコードである.時間を取るというコードを身代わりにする必要があります.
    特殊な条件をシミュレートします.たとえば、ネットワークが切断された条件や、外部サービスが予期せぬエラーを報告した場合などです.ここで著者は、コード遠隔制御レゴロボットを通じて現実のネット線を抜くと、もちろんもっとすごいと笑った.
    隠し情報へのアクセス:一般的に、テストコードがクラス内部実装にアクセスする必要がある場合は、クラス設計に問題があることが多い.Javaにとって、いくつかのプライベート変数などにアクセスすることを意味します.しかし,テストでクラスにテストのためのメソッドを追加する必要があることが判明した場合,1つのテストエージェントをサブクラスとして元のクラスを継承し,これらのメソッドをテストエージェントというサブクラスに追加することを考慮すべきである.
    次に、身代わりをテストするタイプについてお話しします.著者は4つに分けられています.
  • Test Stub
  • Fake Object
  • Test Spy
  • Mock Object

  • 私もすべての正確な中国語の翻訳が何なのか分かりません.ほとんどの人は英語が読めると思いますが、Test Spy(スパイをテストする)の機能が異なることを知っている以外に、ほとんどの人は他の3つの違いを知らない可能性があります.以下、説明します.
    Test Stub:Stubという言葉は、杭やタバコの吸い殻など、短いものを指します.だからTest Stubの特徴は短いことです.著者は良い例を挙げた.例えば、私たちのコードはログを打つライブラリを使った.ログの実際の実現は複雑かもしれない.ログをあるリモートサーバーにプッシュしたり、データベースに保存したりする必要がある.私たちの手元のテストはログの出力に関心を持っていない.次の例を参照して、logメソッドを空にしてください.
       public class LoggerStub implements Logger {
           public void log(LogLevel level, String message) {
            // still a no-op
          }
          public LogLevel getLogLevel() {
            return LogLevel.WARN; // hard-coded return value
          }
    }
    

    Test Stubがメソッドの単純な実装(通常は1行のreturnコードのみ)に対してニーズを満たすことができない場合は、次のFake Objectを使用します.
    Fake Object:ダミー.ダミーオブジェクトの典型的な例は、アナログデータアクセス層である.データ・アクセス・レイヤをシミュレートすることで、データベースにアクセスせずに簡単な削除変更操作を実現し、オブジェクトをメモリに保存できます.例えば、内部配列を維持することで、次のインタフェースをシミュレートする方法を考えることができます.
    public interface UserRepository {
        void save(User user);
        User findById(long id);
        User findByUsername(String username);
    }
    

    Test Spy:ほとんどのテストのコードは、このコードの入力に出力することでコードの正確性を判断することができます.しかし、場合によっては実現できないことがあります.例えば、私たちがテストするものは、実行するコードに出力がないため、コードが特定のインタフェースを呼び出しているかどうかなどをテストすることはできません.この場合、これらのインタフェースにTest Spyを確立して、インタフェースメソッドが実行されたかどうか、インタフェースに入力されたパラメータが正しいかどうかを記録する必要がある.例えば、以下のログのTest Spyについては、特定のログがwriteメソッドで記録されているかどうかを後で検出するためのreceivedメソッドがあります.
    private class SpyTarget implements DLogTarget {
        private List log = new ArrayList();
        @Override
        public void write(Level level, String message) {
            log.add(concatenated(level, message));
        }
        boolean received(Level level, String message) {
            return log.contains(concatenated(level, message));
        }
        private String concatenated(Level level, String message) {
            return level.getName() + ": " + message;
        }
    }
    

    Mock Object:特定のパラメータを受信したときに指定された動作を示すことを規定する補強版のStubです.同時に簡略化版のtest spyとも言える.基本的にはメソッドのパラメータと呼び出しの回数を記録するだけで、他の内部状態を記録しないからだ.このとき、JavaではJMock、Mockito、EasyMockなどのライブラリを選択することができます.実際には以上の4つの身代わりタイプは,Fake Objectが適切でない可能性があるほか,基本的にmockのライブラリで実現できる.
    次の記事では、身代わりをテストする方法を紹介します.