Unit Testing Method Using User Interface Elements

Currently, I am writing several methods that perform some basic operations with form controls, for example Textbox, Groupbox, these operations are common and can be used in any application.

I started writing some unit tests and just wondered if I should use real form controls located in System.Windows.Forms, or should I just mock up the sections I'm trying to test. For example:

Let's say I have this method that takes control, and if it is a text field, it will clear the text property as follows:

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

Then I want to test this method so that I do something like this:

  [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); } } 

Should I add a link to System.Window.Forms to my unit test and use a real Textbox object? or am i doing it wrong?

NOTE. The above code is just an example; I did not compile and run it.

+6
c # unit-testing mocking
source share
3 answers

If you are trying to use the unit test application logic to model the interaction with user interface controls, you must abstraction using the MVC pattern . Then you can simply look at the stub and call the controller methods from your unit tests.

If these are the actual controls you are trying to execute unit test, you have me.

+6
source share

There are several templates that are useful for separating user interface representations from user interface logic, including Model-View-Controller and various implementations of Model-View-Presenter (AKA Humble Dialog). The humble dialogue was specifically designed to simplify unit testing. You must have one of these user interface templates in your design arsenal.

But I found that for simple forms, when the framework supports it, it is quite simple to check directly against real interface elements. I have developed fairly robust user interfaces that have been fully tested in Java Swing and Windows.Forms. I could not manage it in SWT or ASP.NET and return to MVP.

To test such things ...

 [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")); } 

... working with user interface controls works just fine. But if you want to start testing mouse movements, keystrokes, or drag and drop, you'd better choose a more robust user interface template similar to that suggested by Brian.

+5
source share

What you offer will not even compile if your code depends on System.Windows.Forms.Control. Your version of Control and Textbox is just the wrong type.

If instead you separated your interface and logic with the interfaces, then you could do it ... Something like this:

 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"; } } 

Then, in your test, all you have to do is create a false, fake, or drown ITextBox and pass it.

When I do something like this, I create an interface at a slightly higher level ... I create an interface that is very similar to the entire user interface and implements the interface. Then I can customize the interface I need without even knowing that it is a Forms control.

By the way, if you want to go with the approach to creating real controls, think about this blog: http://www.houseofbilz.com/archive/2008/10/12/winforms-automation-extensions.aspx

+3
source share

All Articles