6

我目前正在编写一些对表单控件执行一些基本操作的方法,例如 Textbox、Groupbox,这些操作是通用的,可以在任何应用程序中使用。

我开始编写一些单元测试,只是想知道我应该使用 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 对象吗?还是我做错了?

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

4

3 回答 3

6

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

如果它是您尝试进行单元测试的实际控件,那么您有我。

于 2008-11-19T13:27:46.617 回答
5

有几种模式可用于将 UI 表示与 UI 逻辑分离,包括 Model-View-Controller 和 Model-View-Presenter 的各种化身(AKA Humble Dialog)。Humble Dialog 是专门为简化单元测试而设计的。你绝对应该在你的设计库中拥有这些 UI 模式之一。

但是我发现对于简单的表单,当框架支持它时,直接针对真实的 UI 控件进行测试是非常简单的。我已经在 J​​ava 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 控件工作可以正常工作。但是如果你想开始测试鼠标移动、击键或拖放,你最好选择像 Brian 建议的那样更健壮的 UI 模式。

于 2008-11-19T16:43:25.177 回答
3

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

相反,如果您将 UI 和 Logic 与接口分开,那么您可以这样做……像这样:

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,而无需真正知道它是一个 Forms 控件。

顺便说一句,如果您想采用创建实际控件的方法,请考虑这篇关于它的博客文章:http: //www.houseofbilz.com/archive/2008/10/12/winforms-automation-extensions.aspx

于 2008-11-19T13:28:14.790 回答