2009-12-15 100 views
5

我正在爲我的用戶控件編寫一個測試用例,它將提示使用MessageBox.Show爲用戶操作請求處理或取消操作。 如何設計我的單元測試以模仿用戶交互進行?單元測試Winforms UI

我不想重構將邏輯移動到中間層。這是獲得用戶許可並繼續進行中間層調用的一個簡單情況。任何關於此場景的幫助/想法重構UI也會有所幫助。

+0

所以你想測試一下你的控件在點擊這些控件時會做什麼?或者測試本身具有阻止消息框對話框來查看中間層是否可以安全測試? – Maslow 2010-01-08 16:56:15

回答

6

單擊按鈕無非是調用相應的click事件。所以你可能想要圍繞這一點進行測試。

甚至更​​好(如果情況並非如此),將代碼移出前端,然後圍繞業務操作構建您的單元測試,否則您將通過單擊按鈕來調用。按作者編輯後

更新
你不會得到,只要你不準備分裂的事情這個工作,你不能建立一個圍繞「點擊這裏」單元測試「下,點擊有」。想象一下下面的代碼:

private int MyFunction() 
{ 
    bool insideVariable = false; 
    if(insideVariable) 
     return 1; 
    else 
     return 2; 
} 

你將永遠能夠單元測試,其中insideVariable設置爲true的情況;您可以:

  1. 重構代碼,因此return 1聲明是在某處你的中間層
  2. 重構,以便return 1聲明是在你的GUI的方法。然後您可以測試該功能。

應用程序前端應該很容易替換,所以不應該存儲業務邏輯。單元測試只是居住在主GUI旁邊的另一個前端。

+0

我可以使用SendKeys.SendWait類似的東西,但這裏的問題是ShowDialog是一個阻塞呼叫 – SKG 2009-12-15 20:28:20

+0

你不應該嘗試真的點擊按鈕,但只是像'new Form1()。Button1_Click(this,null)'' 。 – 2009-12-15 20:29:10

+2

+1 - 如果UI擁有足夠的邏輯來重複其操作需要實際使用UI代碼,那麼UI包含的邏輯太多。這可能值得注意的例外 - 在這方面表現邏輯總是很棘手 - 但通常來說,可測試的代碼並不在用戶界面中開始。 – 2009-12-15 20:32:17

3

通過發佈UI方法或相關方法,提供解決方案將變得更容易。也看到TestMethod(s)可以幫助甚至不完整的方法。

如果我瞭解您的測試目的是確定發生在不同的點擊可能性上會發生什麼?

你可以設置一個使用Inversion of ControlDependency Injection這樣觸發MessageBox您的實際方法:

public class ClassUnderTest 
{ 
    private static Func<string, string, MessageBoxButtons, DialogResult> 
     _messageBoxLocator = MessageBox.Show; 
    public static Func<string, string, MessageBoxButtons, DialogResult> 
     MessageBoxDependency 
    { 
     get { return _messageBoxLocator; } 
     set { _messageBoxLocator = value; } 
    } 

    private void MyMethodOld(object sender, EventArgs e) 
    { 
     if (MessageBox.Show("test", "", MessageBoxButtons.YesNo) == 
      System.Windows.Forms.DialogResult.Yes) 
     { 
      //Yes code 
      AnsweredYes = true; 
     } 
     else 
     { 
      //No code 

     } 
    } 

    public bool AnsweredYes = false; 

    public void MyMethod(object sender, EventArgs e) 
    { 
     if (MessageBoxDependency(
        "testText", "testCaption", MessageBoxButtons.YesNo) 
      == 
      System.Windows.Forms.DialogResult.Yes) 
     { 
      //proceed code 
      AnsweredYes = true; 
     } 
     else 
     { 
      //abort code 
     } 


    } 
} 

,然後測試方法(記住包括using Microsoft.VisualStudio.TestTools.UnitTesting;在頂部)會是這樣:

[TestMethod] 
    public void ClassUnderTest_DefaultAnsweredYes_IsFalse() 
    { 
     var classUnderTest = new ClassUnderTest(); 
     Assert.AreEqual(false, classUnderTest.AnsweredYes); 
    } 
    [TestMethod] 
    public void MyMethod_UserAnswersYes_AnsweredYesIsTrue() 
    { 
     //Test Setup 
     Func<string, string, MessageBoxButtons, DialogResult> 
      fakeMessageBoxfunction = 
        (text, caption, buttons) => 
        DialogResult.Yes; 

     //Create an instance of the class you are testing 
     var classUnderTest = new Testing.ClassUnderTest(); 
     var oldDependency = Testing.ClassUnderTest.MessageBoxDependency; 
     Testing.ClassUnderTest.MessageBoxDependency = fakeMessageBoxfunction; 
     try 
     { 
      classUnderTest.MyMethod(null, null); 
      Assert.AreEqual(true, classUnderTest.AnsweredYes); 
      //Assert What are you trying to test? 
     } 
     finally 
     { //Ensure that future tests are in the default state 
      Testing.ClassUnderTest.MessageBoxDependency = oldDependency; 
     } 
    }