使用UI控件的unit testing方法

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

我开始编写一些unit testing,只是想知道我应该使用System.Windows.Forms中的实际表单控件,还是应该模拟我试图测试的部分。 例如:

假设我有这个控制方法,如果它是一个文本框,它将清除文本属性,如下所示:

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

然后我想测试这个方法,所以我做这样的事情:

  [TestMethod] public void TestClear() { List listofcontrols = new List(); 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的referance添加到我的unit testing并使用真正的Textbox对象吗? 还是我做错了?

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

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

如果它是您尝试进行unit testing的实际控件,那么您就拥有了我。

有几种模式可用于将UI表示与UI逻辑分离,包括模型 – 视图 – 控制器和模型 – 视图 – 演示者(AKA Humble Dialog)的各种化身。 Humble Dialog专门用于简化unit testing。 你肯定应该在你的设计库中拥有这些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控件工作正常。 但是如果你想开始测试鼠标移动,击键或拖放,你最好选择一个像Brian建议的更强大的UI模式。

如果您的代码依赖于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