Channels ▼


Unit Testing the UI

Source Code Accompanies This Article. Download It Now.

Unit Testing the User Interface

Using MVP and automatic data binding, unit tests for the view become straightforward. Because the view is now responsible for only visualization of values and responding to binding events, you can cover most of the functionality of the view with two unit tests for each display property:

  • TestVisualizingPropertyX
  • TestBindingPropertyX

In order to run a unit test for the view, it is necessary to launch the Form or Control, and inspect its state by inspecting the child controls within the Form or Control. Because child controls within a parent are typically represented by private member variables, you can leverage a Tester class that extracts the controls from the parent. In Listing Four, the GUITester class uses reflection to traverse the parent's hierarchy to retrieve the specified control by the control's Name property.

public static class GUITester
    public static T FindControl<T>(Control container, string name)
          where T : Control
        if (container is T && container.Name == name)
            return container as T;
        if (container.Controls.Count == 0)
            return null;
        foreach (Control child in container.Controls)
            Control control = FindControl<T>(child, name);
            if (control != null)
                return control as T;
        return null;

Listing Four

Once you can retrieve the child controls, it is straightforward to create a unit test to validate this visualization of a property. All you need to do is launch the form, update the property, and validate the state of the control; see Listing Five.

public class CalculatorFormTest
    public void TestVisualizingOperand2()
        CalculatorForm target = new CalculatorForm();
        TextBox operand2TextBox =
           GUITester.FindControl<TextBox>(target, "_operand2TextBox");
        _target.Operand2 = 100;

Listing Five

Now that you have test coverage for the visualization, you need to ensure that binding works correctly. This can be achieved with a simple unit test validating that the model and view are kept in sync, as in Listing Six.

public class CalculatorFormTest
    public void TestBindingOperand2()
        CalculatorForm target = new CalculatorForm();
        Calculator model = target.Calculator();
        // Update the UI and validate the model
        target.Operand2 = 7;
        Assert.AreEqual(target.Operand2, model.Operand2);
        // Update the model and validate the UI
        model.Operand2 = 9;
        Assert.AreEqual(model.Operand2, target.Operand2);
Listing Six

As long as you create unit tests of this type for each display property, you can add a significant amount of coverage with little unit test code.


By leveraging MVP and automatic data binding, you can create simple unit tests that cover most of the responsibilities of the view. While it is true that some view operations, such as drag-and-drop, are difficult to test, binding and visualization are at the heart of what is happening in a view.

In addition, you can view the wrapper properties used in the example as superfluous. Although it is not necessary to wrap each text box with its own display property, the example serves to demonstrate the simplicity of creating the one-to-one mapping between the presentation property and the view property. How you apply the rule to each new application is up to you.

As long as you adhere to the spirit of MVP, you will find a straightforward approach to unit testing the view.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags


<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags


<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

