TFS2012ビルドサーバーでのチェックイン中に実行されるプロジェクト用の単体テストも多数あります。ローカルでは期待どおりに動作しますが、TFSでタイマーを使用するユニットテストで奇妙な動作が発生することがあります。最後に、その動作を分離するためのクラスとテストを作成しました。
クラス:
public class TestTimerOnServer
{
Timer _MyTimer = new Timer(100);
int _CountsToDo = 100;
public int TimerElapsedCounter = 0;
public TestTimerOnServer()
{
_MyTimer.Elapsed += _MyTimer_Elapsed;
}
public void StartCounting(int argNumberOfCounts, int argIntervalInMs)
{
_MyTimer.Stop();
_MyTimer.Interval = argIntervalInMs;
TimerElapsedCounter = 0;
_CountsToDo = argNumberOfCounts;
_MyTimer.Start();
}
void _MyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (_CountsToDo > TimerElapsedCounter)
TimerElapsedCounter++;
else
_MyTimer.Stop();
}
}
それに対して実行されているテスト:
private void TestTimerServerBehaviour()
{
TestTimerOnServer ttos = new TestTimerOnServer();
ttos.StartCounting(10, 100); // should lead 1000 ms
// we wait 1100 MS
Thread.Sleep(1100);
Assert.AreEqual(ttos.TimerElapsedCounter, 10,"We should have 10
samples, but only " + ttos.TimerElapsedCounter + " have been generated.!");
ttos.StartCounting(50, 100); // should lead 5000 ms
// we wait 6000 MS
Thread.Sleep(6000);
Assert.AreEqual(ttos.TimerElapsedCounter, 50, "We should have 50
samples, but only " + ttos.TimerElapsedCounter + " have been generated.!");
}
ほとんどの場合、このテストは合格しますが、TFSで失敗することもあります。たとえば、50回ではなく2回だけイベントを発生させます。問題は、ここで一般的な単体テストの設計上の欠陥が発生するのか、それともTFSビルドサービスでテストを実行する際に問題が見つかるのかということです。
編集: TFSはVMで実行されています-これが問題の原因である可能性がありますか?
EDIT2-最終調査結果 問題は明らかにTesting-ContextとVMwareの組み合わせでした。@allenによって投稿されたコードを使用して小さなアプリケーションを作成しました。同じコードを使用したテストと、CPUに負荷をかける別のコードを使用しました。
void CPULoader()
{
var action = new Action(() => { while (true);});
Parallel.Invoke(action, action, action, action, action, action, action, action);
}
非常に原始的ですが効率的です。
アプリケーションとCPUローダーを実行している私のハードウェアマシンでは、タイマーイベントが少し遅れて発生します(たとえば、1000ではなく1100ミリ秒)。これまでのところ、Win7はリアルタイムシステムではありません。
VMwareでは、いくつかの組み合わせにより、最大5000ミリ秒の遅延が発生します。1秒かかるはずです...-もちろん、はるかに悪いですが、それでもイベントは発生します。
本当の楽しみは、テストを実行し(その目的のためにコードを無限ループにパックしました)、CPUローダーを起動することから始まります。CPUのロードを停止し、テストの前にイベントが発生しなくなるまで、システム全体が非常に遅くなります。
これが誰かにいくつかのヒントを与えることができることを願っています-タイマー抽象化を使用し、単体テスト中にタイミング動作をモックすることによってテストを修正しました。副作用として、テストは今より速く実行されます:)