2009-12-15 107 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; 
     } 
    }