Sunday, October 12, 2008

Winforms Automation Extensions



kick it on DotNetKicks.com
In preparation for my talk next Saturday, I am publishing the code that I use to help drive my WinForms application via NUnit tests. The idea is simple -- instantiate the form and use extension methods on the controls to find the controls and drive from there.

This is a preliminary release. I will update this file as I find more functionality s needed. It turns out that you don't need much (besides some creativity) to automate WinForms UIs. This set of extension methods will help you get started.

Download WAX -- Winforms Automation Extensions

To run your forms in NUnit, you just need create/show it in the setup and close it in the teardown:
[SetUp]
public void SetUp()
{
_testForm = new FormToTest();
_testForm.Show();
}

[TearDown]
public void TearDown()
{
_testForm.Close();
}


Here is an example of finding a button by name, clicking on it and validating that the app changed the text of the label:
[Test]
public void Test_That_Button_Click_Changes_Text()
{
var button = _testForm.FindByName<Button>("Button1");
var label = _testForm.FindByName<Label>("Label1");

button.SimulateClick();

Assert.That(label.Text, Is.EqualTo("Hello World"));
}
Note that the FindByName method is just a specialization of the Find method. The Find method takes a delegate you can use to find your controls using any method you wish. For instance, say you want to find a control with a known tag:
[Test]
public void Test_Find_With_Custom_Filter()
{
var l1 = _testForm.Find<Control>(target => (target.Tag as string) == "FindTag");

Assert.That(l1.Name, Is.EqualTo("ListBox1"));
}
In my experience, driving the controls directly is the easiest way to automate the UI. For instance, if you have a list control that you want to set, you might write code like this:
[Test]
public void Test_Setting_ListBox()
{
var listBox = _testForm.FindByName<ListBox>("ListBox1");
listBox.SelectedIndex = 1;

Assert.That(listBox.SelectedItem.ToString(), Is.EqualTo("The Test"));
}
If you have any questions or thoughts about this code, please contact me. I want to grow this code over time, and feedback is very welcome.

No comments: