Click here to Skip to main content
Click here to Skip to main content

Automated UI Testing with Guia

, 1 Jul 2010
Rate this:
Please Sign up or sign in to vote.
Unit-Testing of WPF User Controls via UI automation

Introduction

Guia is an open-source library for .NET which supports the automation of WPF applications. The Library allows access to, and remote control of, miscellaneous WPF-components in an easy and comfortable way. So it can easily be used for automated UI testing. A distinctive feature is the possibility to directly run and test WPF windows and UserControls, without the need for a previously created executable application (EXE file). This enables the writing of test cases for the GUI during development and thus to pursue a test driven approach in a consequent manner.

The Guia (Graphical User Interface Automation) library is avaiable at http://guia.codeplex.com.

Using the Code

Imagine you have a complex WPF UserControl. The correctness of the UserControl shall be proved by automatic UI-tests. Maybe you do also use the MVVM pattern. In that case, you might also want to test the data bindings from the view (UserControl) to the view model and vice versa. Since you follow the test driven approach, these things should be tested stand-alone.

Write a Test with Simulated User Operations

In the following example, we are going to write a test-case for a simple WPF UserControl. The UserControl enables to add new persons to a table. The name of the UserControl is "PersonUserControl". The XAML code is not posted here, but it can be downloaded.

The UserControl looks like this:

guia_1.gif

In the test-case, we would like to simulate a user who does the following:

  1. Enter the name
  2. Enter the firstname
  3. Select a country
  4. Invoke the button "Add"

After this procedure, the test-case should verify whether the person has being added properly.

  1. Check if there is a new entry in the data-grid
  2. Check if the cells of the new entry contain the data expected

Now, we setup a unit-test with MSTest. First, we have to start our UserControl. Since this has to be done prior to every test-case execution, we write an initialize method for that purpose:

CustomControl control = null;

[TestInitialize()]
public void MyTestInitialize()
{
    this.control = CustomControl.Start<PersonUserControl>();
}

As we have started the User-Control, we also need to stop it once. We do that in our cleanup method:

[TestCleanup()]
public void MyTestCleanup()
{
    control.Stop();
}

Now, we can start with our test-case which simulates a user adding a new person.

[TestMethod]
public void TestAddPerson()
{
    control.Get<TextBox>("txtFirstname").Value = "Roger";
    control.Get<TextBox>("txtName").Value = "Smith";
    control.Get<ComboBox>("cmbNationality").GetItem("Switzerland").Select();
    control.Get<Button>("btnAdd").Invoke();
    DataGrid_WpfToolkit dataGrid = control.Get<DataGrid_WpfToolkit>("dataGrid");

    Assert.AreEqual("Smith", dataGrid[0, 0].TextValue);
    Assert.AreEqual("Roger", dataGrid[0, 1].TextValue);
    Assert.AreEqual("Switzerland", dataGrid[0, 2].TextValue);
}

When we execute the test-case now, we will notice that a window is opened in the background and the defined data is entered and the actions executed.

Write a Test to Check the Data Binding

We use the MVVM pattern so that we have a view-model for every view (UserControl). Now, we would like to test the proper binding of the view-model to the view. First of all, we need a view model for our UserControl. This view model (PersonUserControlViewModel) is pretty straight-forward and is not posted here. It is avaiable in the sample-project though. Now we want to set the view model as the UserControl's DataContext. For that purpose, we use an action when initializing the UserControl in the test-case:

CustomControl control = null;
PersonUserControlViewModel viewModel = null;

[TestInitialize()]
public void MyTestInitialize()
{
    this.viewModel = new PersonUserControlViewModel();
    this.control = CustomControl.Start<personusercontrol />((c) => c.DataContext = viewModel);
}

First we want to verify whether data entered from a user in the GUI is also avaiable in the view model:

[TestMethod]
public void TestDataBindingGUI2VM()
{
    control.Get<TextBox>("txtFirstname").Value = "Roger";
    control.Get<TextBox>("txtName").Value = "Smith";
    control.Get<ComboBox>("cmbNationality").GetItem("Switzerland").Select();

    Assert.AreEqual("Roger", viewModel.Firstname);
    Assert.AreEqual("Smith", viewModel.Name);
    Assert.AreEqual("Switzerland", viewModel.Nationality);
}

As you will see, this test succeded.

Now we would like to verify the reverse. If the view model is changed, the GUI should also update immediately.

[TestMethod]
public void TestDataBindingVM2GUI()
{
    viewModel.Firstname = "Roger";
    viewModel.Name = "Smith";
    viewModel.Nationality = "Switzerland";

    Assert.AreEqual("Roger", control.Get<TextBox>("txtFirstname").Value);
    Assert.AreEqual("Smith", control.Get<TextBox>("txtName").Value);
    Assert.AreEqual("Switzerland", 
	control.Get<ComboBox>("cmbNationality").SelectedItem.TextValue);
}

Write a Test for an Entire Application

Until now, we only tested WPF UserControls. Guia also provides the possibility to automate and test entire applications. This feature can be used to write automated acceptance-tests for example.

The following code starts and tests an entire application. The sample application shows a window named "Sample Main Window" which contains the previously introduced UserControl.

[TestMethod]
public void TestEntireApp()
{
    // Init
    Application app = Application.Start(@"C:/Sample.exe");
    Window window = app.GetWindowByName("Sample Main Window");

    // Simulate user interactions
    window.Get<TextBox>("txtFirstname").Value = "Roger";
    window.Get<TextBox>("txtName").Value = "Smith";
    window.Get<ComboBox>("cmbNationality").GetItem("Switzerland").Select();
    window.Get<Button>("btnAdd").Invoke();
    DataGrid_WpfToolkit dataGrid = window.Get<DataGrid_WpfToolkit>("dataGrid");

    // Assertions
    Assert.AreEqual("Smith", dataGrid[0, 0].TextValue);
    Assert.AreEqual("Roger", dataGrid[0, 1].TextValue);
    Assert.AreEqual("Switzerland", dataGrid[0, 2].TextValue);
}

Further examples and code-snippets can be found in the official documentation.

History

  • 1st July, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Guia-Project

Switzerland Switzerland
No Biography provided
Group type: Collaborative Group

1 members


Comments and Discussions

 
Generalsource does not compile Pinmembercorkumortoo7-Jul-10 23:02 
AnswerRe: source does not compile [modified] PingroupGuia-Project8-Jul-10 1:41 
Generalproblem with source Pinmembercorkumortoo7-Jul-10 5:09 
The test program fails with a TypeInitialization Error
The source code opens with lots of error
 
Am sure it works fine on your machine...Confused | :confused:
 
Your project is very interesting --if only it can be made to
work on other machines...Sigh | :sigh:
AnswerRe: problem with source PingroupGuia-Project7-Jul-10 12:30 
GeneralRe: problem with source Pinmembercorkumortoo7-Jul-10 22:01 
AnswerRe: problem with source PingroupGuia-Project8-Jul-10 2:30 
GeneralRe: problem with source Pinmembercorkumortoo8-Jul-10 3:23 
GeneralRe: problem with source PingroupGuia-Project9-Jul-10 9:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 1 Jul 2010
Article Copyright 2010 by Guia-Project
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid