2012-01-25 101 views
2

我們正在開發一個使用TDD的WPF應用程序。由於我們已經在這個解決方案上工作了將近兩年,我們已經寫了大量的測試(現在幾乎有2000個Unittests)。如何優化驗證異步代碼的測試?

有一些類需要實現多線程和異步功能。例如可以發送和接收消息並解析它們的通信組件。依賴關係總是使用RhinoMocks來模擬。

參加測試方法針對這些類看起來非常相似,如下:

[TestMethod] 
public void Method_Description_ExpectedResult(){ 
    // Arrange 
    var myStub = MockRepository.GenerateStub<IMyStub>(); 
    var target = new MyAsynchronousClass(myStub); 

    // Act 
    var target.Send("Foo"); 
    Thread.Sleep(200); 

    //Assert 
    myStub.AssertWasCalled(x => x.Bar("Foo")); 
} 

正如你所看到的,這個測試運行,由於Thread.sleep代碼()至少爲200毫秒。我們優化了測試,使用活動輪詢方法s.th替換AssertWasCalled。像這樣:

public static bool True(Func<bool> condition, int times, int waitTime) 
{ 
    for (var i = 0; i < times; i++) 
    { 
     if (condition()) 
      return true; 
     Thread.Sleep(waitTime); 
    } 

    return condition(); 
} 

現在我們可以使用這個WaitFor.True(...)通過改變AssertWasCalled的方法:

var fooTriggered = false; 
myStub.Stub(x => x.Bar("Foo")).Do((Action)(() => fooTriggered = true))); 

WaitFor.True(() => fooTriggered, 20, 20); 
Assert.IsTrue(fooTriggered); 

此結構將終止早,如果條件滿足,但無論如何 - 這對我們來說需要很長時間。運行我們所有的2000年測試需要大約5分鐘(構建和運行它們)。

有沒有什麼聰明的技巧我們可以如何優化代碼?

回答

2

您可以使用顯示器。我在做這件事,所以請原諒我,如果這是不太編譯,但它會看起來是這樣的:在監控之內書面不能運行,直到它是免費的

[TestMethod] 
public void Method_Description_ExpectedResult(){ 
    // Arrange 
    var waitingRoom = new object(); 
    var myStub = MockRepository.GenerateStub<IMyStub>(); 
    myStub.Setup(x => x.Bar("Foo")).Callback(x => 
     { 
      Monitor.Enter(waitingRoom); 
      Monitor.Pulse(waitingRoom); 
      Monitor.Exit(waitingRoom); 
     } 

    var target = new MyAsynchronousClass(myStub); 

    // Act 

    Monitor.Enter(waitingRoom); 
    target.Send("Foo"); 
    Monitor.Wait(waitingRoom); 
    Monitor.Exit(waitingRoom); 

    //Assert 
    myStub.AssertWasCalled(x => x.Bar("Foo")); 
} 

代碼。測試將導致代理線程等待,直到Monitor.Wait被調用。然後回調可以進入並監控Monitor。然後測試會「醒來」,一旦回調退出監視器,控制權就會恢復並退出,從而允許您斷言。

我唯一沒有提到的是如果Bar(「Foo」)沒有被調用,它會掛起,所以你可能想要一個定時器脈衝線程。

如果您使用它,您可以創建一個爲您執行復雜監控位的類。 This is one I wrote來處理UI自動化中的異步檢查;適應它爲你正在做什麼可能會幫助你。

+0

非常感謝,我喜歡這種測試方式!將嘗試這一個。 – Guffel

+0

哦,看,我沒有Monitor.Wait(waitingRoom,) - 所以不需要做怪異的定時器gubbins。尼斯。 – Lunivore