+++
I am starting a series of posts introducing some of the facilities available in TestApi, a test and utility API library, which we recently released on CodePlex. Most of this content is already available in the documentation provided with the library.
The first post is on input injection – a fairly common activity in UI testing.
Input injection is the act of simulating user input. In general, there are several ways to simulate user input, in the following progressively increasing levels of realism:
Technique A is framework-specific; what works for WPF does not work for Windows Forms and vice versa. Technique B is less framework-specific than A, but still has limitations, because some frameworks differ in their implementations of the required accessibility interfaces. Techniques C and D are OS-specific. Technique D is significantly more difficult to implement and deploy than C, without a corresponding increase in its level of realism. Technique E is universal, albeit much slower and much more expensive than the other options.
The TestApi library provides facilities both for B (through the AutomationUtilities class) and for C (through the Mouse and Keyboard classes), which are the most generally useful techniques of input simulation.
The AutomationUtilities class provides wrappers for common UIA operations, such as discovery of UI elements. The first example below demonstrates how to discover and click a WPF Button in a WPF Window, by using the AutomationUtilities class and the Mouse class.
// // EXAMPLE #1 // This code below discovers and clicks the Close button in an About dialog box, thus // dismissing the About dialog box. // string aboutDialogName = "About"; string closeButtonName = "Close"; AutomationElementCollection aboutDialogs = AutomationUtilities.FindElementsByName( AutomationElement.RootElement, aboutDialogName); AutomationElementCollection closeButtons = AutomationUtilities.FindElementsByName( aboutDialogs[0], closeButtonName); // // You can either invoke the discovered control, through its invoke pattern... // InvokePattern p = closeButtons[0].GetCurrentPattern(InvokePattern.Pattern) as InvokePattern; p.Invoke(); // // ... or you can handle the Mouse directly and click on the control. // Mouse.MoveTo(closeButton.GetClickablePoint()); Mouse.Click(MouseButton.Left);
The second example below demonstrates how to discover a TextBox instance and type in it, using the Mouse and Keyboard classes as wrappers of common mouse and keyboard operations:
// // EXAMPLE #2 // Discover the location of a TextBox with a given name. // string textboxName = "ssnInputField"; AutomationElement textBox = AutomationUtilities.FindElementsByName( AutomationElement.RootElement, textboxName)[0]; Point textboxLocation = textbox.GetClickablePoint(); // // Move the mouse to the textbox, click, then type something // Mouse.MoveTo(textboxLocation); Mouse.Click(MouseButton.Left); Keyboard.Type("Hello world."); Keyboard.Press(Key.Shift); Keyboard.Type("hello, capitalized world."); Keyboard.Release(Key.Shift);
The Mouse and Keyboard classes in the TestApi library can be used for automating of any application, running on Windows. The classes are completely policy- and context-free – their usage is not dependent on a specific test framework or on a specific test workflow. TestApi provides full source code and XML documentation for these classes, so you can either integrate them in your own projects or reference the pre-built DLLs.
Note that, even though Mouse, Keyboard and AutomationUtilities make the life of the test automation developer quite a bit easier, UI testing is tricky and should be avoided whenever possible. It’s always preferable to design your application as a multi-tier application, with a “thin” UI layer, so that you can bypass the UI in most of your tests.