2008-11-19 84 views
6

我目前正在编写一些方法,对窗体控件进行一些基本操作,例如文本框,组框,这些操作都是通用的,并且可以在任何应用程序中使用。使用UI控件的单元测试方法

我开始编写一些单元测试,只是想知道应该使用System.Windows.Forms中的真实窗体控件,还是应该模拟我试图测试的部分。因此,例如:

说我有这个方法,这需要控制,如果它是一个文本框将清除Text属性是这样的:

 public static void clearall(this Control control) 
     { 
      if (control.GetType() == typeof(TextBox)) 
      { 
       ((TextBox)control).Clear(); 
      } 
     } 

然后我想测试这个方法让我做一些事情像这样:

 [TestMethod] 
     public void TestClear() 
     { 
      List<Control> listofcontrols = new List<Control>(); 
      TextBox textbox1 = new TextBox() {Text = "Hello World" }; 
      TextBox textbox2 = new TextBox() { Text = "Hello World" }; 
      TextBox textbox3 = new TextBox() { Text = "Hello World" }; 
      TextBox textbox4 = new TextBox() { Text = "Hello World" }; 

      listofcontrols.Add(textbox1); 
      listofcontrols.Add(textbox2); 
      listofcontrols.Add(textbox3); 
      listofcontrols.Add(textbox4); 

      foreach (Control control in listofcontrols) 
      { 
       control.clearall(); 
       Assert.AreEqual("", control.Text); 
      } 
     } 

我应该加入到全球化志愿服务青年来System.Window.Forms我的单元测试和使用真正的文本框对象?还是我做错了?

注意:上面的代码只是一个例子,我没有编译或运行它。

回答

6

如果您尝试通过模拟与UI控件的交互来单元测试应用程序逻辑,则应该使用MVC pattern进行一些抽象。然后,您可以拥有存根视图并从单元测试中调用控制器方法。

如果它是您正在尝试单元测试的实际控件,那么您已经拥有了我。

+0

我同意,在测试.NET Framework时没有真正的用处。微软已经在很大程度上做到了这一点:)。 – Tigraine 2008-11-20 00:34:02

3

如果你的代码依赖于System.Windows.Forms.Control,你所建议的甚至不会编译。您的Control和Textbox版本只是错误的类型。

相反,如果你用分离的界面UI和逻辑,那么你可以这样做......事情是这样的:

public interface ITextBox 
{ 
    public string Text {get; set;} 
} 

public class TextBoxAdapter : ITextBox 
{ 
    private readonly System.Windows.Forms.TextBox _textBox; 
    public TextBoxAdapter(System.Windows.Forms.TextBox textBox) 
    { 
     _textBox = textBox; 
    } 

    public string Text 
    { 
     get { return _textBox.Text; } 
     set { _textBox.Text = value; } 
    } 
} 

public class YourClass 
{ 
    private ITextBox _textBox; 
    public YourClass(ITextBox textBox) 
    { 
     _textBox = textBox; 
    } 

    public void DoSomething() 
    { 
     _textBox.Text = "twiddleMe"; 
    } 
} 

然后,在您的测试,所有你需要做的就是创建一个假的或存根ITextBox并通过它。

当我做这样的事情时,我创建了一个稍高一级的接口......我创建了一个接口,看起来很像整个UI,并有UI实现界面。然后,我可以将所有需要的用户界面都转换出来,而无需真正知道它是一个Forms控件。

顺便说一句,如果你想要去创造实际控制的方法,可以考虑这个博客帖子大约是:http://www.houseofbilz.com/archive/2008/10/12/winforms-automation-extensions.aspx

5

有几种模式,是有用的从UI逻辑,包括型号 - 分离UI演示View-Controller和Model-View-Presenter(AKA Humble Dialog)的各种版本。 Humble Dialog专门为编写单元测试而编写的。你应该在你的设计工具库中有一个这样的UI模式。

但是我发现对于简单的表单,当框架支持它时,直接对真正的UI控件进行测试非常简单。我已经在Java Swing和Windows.Forms中完全构建了相当健壮的用户界面(UI)。我无法在SWT或ASP.NET中管理它,并恢复为MVP。

为了测试这样的事情......

[Test] public void ShouldCopyFromAvailableToSelectedWhenAddButtonIsCLicked(){ 
    myForm.AvailableList.Items.Add("red"); 
    myForm.AvailableList.Items.Add("yellow"); 
    myForm.AvailableList.Items.Add("blue"); 

    myForm.AvailableList.SelectedIndex = 1; 
    myForm.AddButton.Click(); 

    Assert.That(myForm.AvaiableList.Items.Count, Is.EqualTo(2)); 
    Assert.That(myForm.SelectedList.Items[0], Is.EqualTo("yellow")); 
} 

...直接针对UI控件工作正常。但是如果你想开始测试鼠标移动,击键或拖放,你最好选择一个更健壮的UI模式,比如Brian建议的模式。