7

タイマーを使用してテスト対象の被験者がいて、一定の間隔で何らかのアクションが実行される場合、それをテストするための良い方法は何ですか?

1つの方法 は、タイマーをインターフェースでラップし、依存関係として挿入することです。

ただし、さらに別の抽象化を作成することは避けたいと思います。タイマーではなく更新間隔を挿入することで、それを回避できるようです。次に、私のテスト(AAAスタイルのテストを想定)では、テストの実行に時間がかからないように、非常に小さい時間値を使用して、ActThread.Sleepの後とAssertの前に配置しました。

それは悪い考えですか?おそらくTDDの原則に完全には従わないことは知っていますが、すべてを契約で囲み、それを注入するのをやめるラインが必要なようです。

4

2 に答える 2

6

睡眠の量がテストで重要ではなく、iを1ミリ秒に設定できる場合は、テストで1ミリ秒だけ睡眠するだけで問題ありません。

ただし、タイムアウトや特定の時点で実行される特定のアクションを使用して複雑なタイミング動作をテストする場合は、時間の概念を抽象化し、依存関係として挿入する方がすぐに簡単になります。そうすれば、コードがリアルタイムを通過しているかのように動作していても、テストは仮想時間で動作し、遅延なく実行できます。

時間を仮想化する簡単な方法は、次のようなものを使用することです。

interface ITimeService {

  DateTime Now { get; }

  void Sleep(TimeSpan delay);

}

class TimeService : ITimeService {

  public DateTime Now { get { return DateTime.UtcNow; } }

  public void Sleep(TimeSpan delay) { Thread.Sleep(delay); }

}

class TimeServiceStub : ITimeService {

  DateTime now;

  public TimeServiceStub() {
    this.now = DateTime.UtcNow;
  }

  public DateTime Now { get { return this.now; } }

  public void Sleep(TimeSpan delay) {
    this.now += delay;
  }

}

タイマーの起動など、より反応的な動作が必要な場合は、このアイデアを拡張する必要があります。

于 2012-02-02T22:57:29.187 に答える
2

依存関係の注入は、本番コード内に「テスト」コードが含まれないようにする方法です(単体テストのためだけに間隔を設定するなど)。

ただし、この場合、設定された間隔コードを使用しますが、単体テストと本番の両方で使用します。プロダクションで設定し、単体テストで非常に少量(10ms?)に設定しました。そうすれば、本番環境でデッドコードがぶら下がることはありません。

間隔を設定すると、なぜThread.Sleepが必要なのかわかりません。サブジェクトからイベントを取得するまで(またはサブジェクトを継続的にポーリングするまで)、ユニットテストブロックを用意してください。使用している方法が何であれ。

于 2012-02-02T23:04:52.950 に答える