MSDN Magazine - March 2009 - (Page 41) Microsoft Windows SDK and is available as a free download from microsoft.com/downloads. Figure 4 Examining Controls with UISpy Figure 5 UI Test Automation Code Structure using using using using System; System.Diagnostics; System.Threading; System.Windows.Automation; namespace Harness { class Program { static void Main(string[] args) { try { Console.WriteLine(“\nBegin WPF UIAutomation test run\n”); // launch CryptoCalc application // get reference to main Window control // get references to user controls // manipulate application // check resulting state and determine pass/fail Console.WriteLine(“\nEnd automation\n”); } catch (Exception ex) { Console.WriteLine(“Fatal: “ + ex.Message); } } // Main() } // class } // ns Figure 6 Determining What Happened if (p == null) throw new Exception(“Failed to find CryptoCalc process”); else Console.WriteLine(“Found CryptoCalc process”); // Next I fetch a reference to the host machine’s Desktop as an // AutomationElement object: Console.WriteLine(“\nGetting Desktop”); AutomationElement aeDesktop = null; aeDesktop = AutomationElement.RootElement; if (aeDesktop == null) throw new Exception(“Unable to get Desktop”); else Console.WriteLine(“Found Desktop\n”); The screenshot in Figure 4 shows the result of targeting the Button control on the CryptoCalc application. From a test automation perspective, the important fields for identifying application controls are the ControlType (ControlType.Edit in this case), AutomationId (button), and Name (Compute) values. The important field for manipulating application controls is the ControlPatterns list (Invoke). Manually testing even this tiny CryptoCalc application through its user interface would be boring, error-prone, time-consuming, and inefficient. You would have to enter an input, click the Compute button control, visually verify the answer, and manually record the pass/fail result. A much better approach is to use the Microsoft UI Automation library to write test automation that simulates a user exercising the application and then determines whether the application responded correctly. By automating tedious test cases, you can free up time for more interesting and useful manual test cases in which your experience and intuition play a big role. The overall structure of the test harness that produced the output shown in Figure 1 is listed in Figure 5. I launched Visual Studio and created a new console application program. I used C#, but you should be able to easily convert my test automation code to Visual Basic .NET if you want to. Next, I added Project References to the UIAutomationClient.dll and UIAutomationTypes.dll libraries. These libraries are part of the .NET Framework . but are not visible by default to a Visual Studio project. The libraries are typically located in the C:\Program Files\Reference Assemblies\Microsoft\Framework\v. directory. Note that the UIAutomationClient.dll library contains the key classes needed for test automation. The UIAutomationTypes.dll library contains various type definitions used by MUIA test automation. For convenience, I add using statements that point to the System.Diagnostics namespace (so I can easily use the Process class), and to the System.Threading namespace (so I can easily use the Thread.Sleep() method). As usual with any test automation, I wrap my harness with a top-level try-catch block to handle any fatal errors. My test automation code begins by launching the application under test: Console.WriteLine(“Launching CryptoCalc application”); Process p = null; p = Process.Start(“..\\..\\..\\CryptoCalc\\bin\\Debug\\CryptoCalc.exe”); Now, before I attempt any test automation, I need to verify that the process associated with the CryptoCalc application under test is registered on the host machine. Although I could pause my test harness by simply inserting a Thread.Sleep statement, I have no good way of knowing how long to pause. A better approach is to use a smart delay-loop: int ct = 0; do { Console.WriteLine(“Looking for CryptoCalc process. . . “); ++ct; Thread.Sleep(100); } while (p == null && ct < 50); application under test. A good way to do this is to use the UISpy tool. For those who don’t know, UISpy is the WPF equivalent of the old Spy++ tool and allows you to examine properties of the UI components of a WPF application. The UISpy tool is part of the msdnmagazine.com Here I pause for milliseconds each time through the delay loop. The harness exits the delay loop if the process object becomes March 2009 41 http://www.microsoft.com/downloads http://www.msdnmagazine.com
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.