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:
1: [SetUp]
2: public void SetUp()
3: {
4: _testForm = new FormToTest();
5: _testForm.Show();
6: }
7:
8: [TearDown]
9: public void TearDown()
10: {
11: _testForm.Close();
12: }
Here is an example of finding a button by name, clicking on it and validating that the app changed the text of the label:
1: [Test]
2: public void Test_That_Button_Click_Changes_Text()
3: {
4: var button = _testForm.FindByName<Button>("Button1");
5: var label = _testForm.FindByName<Label>("Label1");
6:
7: button.SimulateClick();
8: Assert.That(label.Text, Is.EqualTo("Hello World"));
9: }
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:
1: [Test]
2: public void Test_Find_With_Custom_Filter()
3: {
4: var l1 = _testForm.Find<Control>(target => (target.Tag as string) == "FindTag");
5: Assert.That(l1.Name, Is.EqualTo("ListBox1"));
6: }
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:
1: [Test]
2: public void Test_Setting_ListBox()
3: {
4: var listBox = _testForm.FindByName<ListBox>("ListBox1");
5: listBox.SelectedIndex = 1;
6:
7: Assert.That(listBox.SelectedItem.ToString(), Is.EqualTo("The Test"));
8: }
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.