使用UI控件的单元测试方法

6

我正在编写一些与表单控件相关的基本操作方法,例如文本框、组框等等。这些操作是通用的,可以在任何应用程序中使用。

我开始编写一些单元测试,并想知道是否应该使用 System.Windows.Forms 中找到的真实表单控件,还是只模拟我要测试的部分。例如:

假设我有这个方法,它接受一个控件,如果它是文本框,它将清除文本属性:

        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的引用并使用真正的Textbox对象?还是我做错了?

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

3个回答

6
如果您想通过模拟与UI控件的交互来进行应用逻辑的单元测试,您应该使用MVC模式进行一些抽象。然后,您只需要拥有一个存根视图,并从您的单元测试中调用控制器方法。
如果您要进行实际控件的单元测试,那么我就不知道了。

我同意,在测试.NET Framework方面没有真正的用处。微软已经在相当大的范围内进行了测试 :)。 - Tigraine

5

有几种模式对于将UI展示与UI逻辑分离非常有用,包括Model-View-Controller和Model-View-Presenter的各种形式(也称为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建议的模式。


3

如果你的代码依赖于System.Windows.Forms.Control,那么你所建议的内容甚至无法编译。你的Control和Textbox版本是错误的类型。

相反,如果你使用接口分离你的用户界面和逻辑,那么你可以这样做……类似这样:

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实现这个接口。然后,我可以尽情地调整UI,而不必真正知道它是一个表单控件。
顺便说一下,如果你想采用创建实际控件的方法,请考虑阅读这篇博客文章:http://www.houseofbilz.com/archive/2008/10/12/winforms-automation-extensions.aspx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接