Http://blog.9cbs.net/cswcafe/archive/2005/02/23/29838.aspx
Lightweight UI test automation with .NET development
James McAffrey
Download this article: Testrun0501.exe (131KB)
This page
Test application test automation script operation Test application check application status discussion
Manual user interface test is the most basic software test type, most software engineers use this type of test type. In contradictions, automated user interface tests may be one of the most technical challenges in the prepared test type. The Microsoft® .NET environment provides you with many ways to write automated user interface testing. A common and useful method is to record keys, mouse movements, and click, and then play back in the application to ensure that it is executed in a desired manner. (For more information on this method, see the BugsLayer column of John Robbins in MSDN® Magazine, MSDN® Magazine. This issue of MSDN Magazine's Paul Dilascia column also explains how to send this type of input to this type. Another application.) In this month, I will explore another method for the .NET application to write a lightweight UI test automation.
The best way is to discuss with a screen snapshot. Figure 1 shows that I have a virtual application to test. It is a color synthesizer application that allows users to type a color in text box control, and then type or select a color in ComboBox, click the button, and listbox will display a message, indicating two colors "mixing" the result of. In Figure 1, purple is generated according to the application, red and blue. UI Test Automation is a console application that launches a form to be tested, analog user mobile application form, definition, and adjustment of the size of the application form, set the text box, and ComboBox control, and click the button control . Test Automation Check the results status of the application, verify that the ListBox control contains the correct message and records the "pass" result. The screen snapshot in Figure 1 is captured before the test automation analog user clicks File | EXIT.
Figure 1 Form UI Test Automation
In the following chapter, I will briefly introduce the virtual application I tested, explain how to use the reflection and System.Windows.Forms.Application class to launch the application form in the test automation program, describe how to use the System.Reflection namespace The method simulates the user's operation and check the application status, and describes how to expand and modify the test system to meet your needs. I think, no matter what role you play in a software production environment, you can quickly write a lightweight UI test automation can make your skills greatly improve. In addition, even if you are using an existing framework (such as NUnit), these same technologies can also be integrated into your own unit test management.
Waiting for the application
Let's take a look at the application to test the application to understand the target of testing automation. The color synthesizer application to be tested is a simple Windows® form. The application's code is written in C #, but I will introduce the UI automation technology to you to use any applications written in .NET as the target. I accept the Visual Studio® .NET default control name Form1, TextBox1, ComboBox1, Button1, and ListBox1. Of course, in the actual application, you should change the name of the control to reflect their functions. I added three virtual menu items: File, Edit and View. The code listed in Figure 2 is the main content of the application to be tested.
When a user clicks on the Button1 control, the application gets the value in the TextBox1 and ComboBox1 controls. If these two color strings match, this color message will be displayed. If the text box and the ComboBox control include "RED" and "Blue", the result message "purple" is displayed. If the text box and the ComboBox control are combined with any other color, the result message "Black" is displayed. Because this is just a virtual application used to demonstrate, I want the code as short, so I don't check the input parameters as in the actual application. Although this application is very simple, it has most of the basic features of Windows applications required for automated UI tests. Even for such a small application, it is also very cumbersome to test its user interface. It is easy to have error, and it is time consuming. You must type some inputs, click the button control, an intuitive verification result message, and record the result into the Excel spreadsheet or other data store. Because the application accepts the free input in the text box control, the possible test input is unlimited, so you must test the behavior of the application to understand the application. For all the above operations, once the application code changes, you must perform the same manual test from the head. Writing unit test is a better way because these tests allow you to simulate users using the application, then determine if the application is correctly responding correctly.
Back to top
Test automation script
Figure 3 shows the overall structure of test automation management, Figure 4 shows the code outline. Here I use C #, but you can easily modify the code to any .NET-based language.
Figure 3 UI test automation structure
I first add and declare the reference to System.Windows.Forms, System.Reflection and System.Threading Namespace. Because the console application does not quote System.Windows.Forms.dll by default, you need to add item references to System.Windows.Forms.dll files using the classes in this namespace. System.Windows.Forms Namespace contains the Forms class and the Application class, which are used in this solution. I use the class in System.Reflection to get and set the value of the form control and call the method associated with the form. Use the method in System.Thread to manage the startup form from the console application test.
I declare three types of scope objects because there are several methods in test management to use them:
Static form testform = null;
Static BindingFlags Flags = BindingFlags.public |
Bindingflags.nonpublic |
Bindingflags.Static | bindingflags.instance;
Static int delay = 1500;
Because the color synthesizer application is just a Windows form, I declare an Form object to represent it. There are many ways to use the BindingFlags object as a filter in System.Reflection namespace. I set up a value of 1500 (ms) for Thread.sleep method, so that the time of test automation can be paused for 1.5 seconds. I use this code to launch the application to be tested:
Console.writeline ("/ NLAUNCHING WINAPP Under Test");
String exepath = "c: //formuiautomation//winapp//bin//debug//winapp.exe";
Testform = launchapp (Exepath, "WinApp.form1"); I defined the Launchapp method in Figure 5 and its Helper method RunApp. This code has little rows, but the effect is large. Please note that in order to simply, I hardly encode the path to the test application executable file (in your own test, you may want to use the parameter to indicate this information to make the test automation more flexible). The Launchapp method accepts the path of the application executable file and the name of the application form, and returns an object representing the form. Launchapp uses the Assembly.LoadFrom static method to create an instance of the Assembly object instead of being created by explicitly calling constructor.
Next, the assembly.gettype method returns a type representing the application form, then I use the assembly.createInstance method to create a reference to the test form. Then I initiate a new thread to actually launch the application form. Application.run method starts a message loop in the current thread; because I want to work in the form, I need to make Application.run run in my own thread, so that the loop will not block my process. By using this technique, testing automated console applications management and forms will run under different threads but the same process. This approach allows them to communicate with each other - that is, test management can send instructions to the Windows Form.
Back to top
Operation to be tested
After starting the application to be tested, I simulate the user operating the application form. The sample test scheme begins with the size of the mobile form and the adjustment form, as shown below:
Console.writeline ("Moving Form");
SetFormPropertyValue ("location", new system.drawing.point (200, 200));
SETFORMPROPERTYVALUE ("location", new system.drawing.point (500, 500));
Console.writeline ("resizing form");
SetFormPropertyValue ("size", new system.drawing.size (600, 600));
SetFormPropertyValue ("size", new system.drawing.size (300, 320));
The SetFormPropertyValue method performs all the work (see Figure 6). I use the Object.gettype method to create the Type object representing the application form, and then use the object to obtain the PropertyIfo object that references the form attribute (for example, a Location property or size property). Once you have an attribute information object, you can use the PropertyInfo.setProperty method to operate it. SetProperty accepts three parameters. The first two may be what you want - for reference to the object to change the property and the reference to the new attribute value.
The third parameter is required because some attributes (such as the Items attribute of the ListBox control) are indexed. The mobile form and changes the form size I do here is actually not related to the test application feature, but I want to tell you how to achieve your test plan. Also note that I am using the ISYNCHRONIZEINVOKE interface that the Form class (actually is its Control base class). You should only access the properties of the Controls (containing the FORM) control by having the control underlying window handle. For the form to be tested, the thread is thread initiated to run Application.Run. Since my test management is running in a separate thread, I need to send access to the property and method of the control to the thread, so that the INVOKE method of the control is integrated (this method and attribute are IsynchronizeInvoke Part of the interface). For more information about IsynchronizeInvoke, see MSDN Magazine Articles in Ian Griffith in February 2003: Give Your .Net-Based Application A Fast And Responsive Ui With Multiple Threads. Now I am ready to simulate the user in a text box control, select a color from the ComboBox control:
Console.writeline ("/ NSETTING TEXTBOX1 To 'Yellow');
SetControlPropertyValue (TextBox1 "," Text "," Yellow ");
Console.WriteLine ("Setting TextBox1 to 'Red');
SetControlPropertyValue ("TextBox1", "Text", "Red");
Console.Writeline ("Selecting ComboBox1 to 'Green');
SetControlPropertyValue ("ComboBox1", "SELECTEDITEM", "Green");
Console.writeline ("Selecting ComboBox1 to 'Blue');
SetControlPropertyValue ("ComboBox1", "SELECTEDITEM", "Blue");
I will set the TextBox1 to "Yellow" and set it to "RED" and set the ComboBox1 to "Green" and set to "Blue". All actual work is done by the setControlPropertyValue method shown in Figure 7.
I use the thread.sleep method to pause test automation to ensure that the application is launched and running. After creating the Type object that represents the application form type, I use the type.getfield method to retrieve the information of the specified field (control) in the Form object. Then call the fieldInfo.gettype method to get the TYPE object that represents the control you want to operate. Once you have a control object, I can operate the control object like a Form object, which is the PropertyInfo of the control, and then call the SetValue method. For SetFormPropertyValue, you need to make sure that all attribute changes are in the correct thread. Note that test automation does not directly simulate very low levels of user operations. For example, automation does not simulate each keystroke to the TextBox1 control, but directly set the Text property. Similarly, automation does not simulate the click of the COMBOBOX1 control, but set the SelectEdItem property. This is a design defect in my test automation system. To taking that way, you can do it according to John Robbins in the previous article.
After the simulation user is typed in the text box and the ComboBox control, the automation will simulate click button control:
Console.writeline ("Clicking Button1");
InvokeMethod ("Button1_Click", New Object [Null, Eventargs.empty});
I have defined the INVOKEMETHOD method shown in Figure 8.
InvokeMethod obtains the Type object that represents the application form to be tested by calling the Object.gettype method. Then I use Type.getMethod to get the information of the specified method, and call MethodBase.invoke to perform the specified method. INVOKE accepts two parameters. The first is a form instance to which it wants to call the method, the second is the parameter array of methods. For button controls, click Method, the signature is as follows:
Private Void Button1_Click (Object Sender, System.EventArgs E) In order to meet the parameters of the Button1_Click method, I need to pass a sender's object and an EventArgs object representing the optional event data. For the button clicking, I ignore the value of the first parameter, although for the actual test system, I should transmit the control as a sender that calls the method (the implementation of the method may depend on the access to the control, if This event handler method is used as a handler for multiple controls, this information is particularly useful). For the second parameter, I pass an empty EventArgs object.
Note that the test automation is to simulate the button clicked by the related method of the button control, not by triggering event simulation. When the actual user clicks the button, it generates a Windows message that handles the message and converts it into a managed event. This event will cause a specific (or a group) method. So if the application is a method for the button, UI test automation does not capture logic errors (although each test will fail, you will quickly find problems). This problem can be corrected, and the method is to obtain the underlying multi-channel broadcast delegate using the reflected event, and then use the entrusted GetInvocationList method when the event is triggered to get the list of all delegates to call. You can then call each delegate. Or you can use event EventInfo and its getraiseMethod method to get MethodInfo, but do only return only a customized trigger method, and support only C and Microsoft Intermediate Language (MSIL). Once again, all of these issues can be avoided by using the Send Keys method discussed earlier. Back to top
Check the application status
After automation, by simulating the status of the application form, you can check if the system status is set to see if the application is correctly responded correctly (see Figure 9).
I set up a Boolean variable called "pass", set it to true - I assume that the status of the application is correct and checks the status, if there is an error, set the pass to false. Check the TextBox1 control to make sure its text property is correctly set to "Red". Then check to make sure the value of ComboBox1 is "Blue", and ListBox1 displays the correct message "Result is Purple". If everything is passed, the Pass message is printed, otherwise print the FAIL message.
Checking the key to the application system status is the GetControlPropertyValue method I encoded, as shown in Figure 10. First use Object.getType to create a TYPE object representing the application form. Then use Type.GetField to get information about the specified control. Next, use GetType to get the TYPE object indicating the control. Finally use the getProperty to get information about the specified properties of the control, and use the getValue method to get the control attribute value. GetValue requires an index object parameter because the property can be indexed (for example, when I try to get the Items property of the ListBox control).
Please note that checking the text in the ListBox1 control is flexible than checking the text in the TextBox1 control. I use my getControlPropertyValue method to access the items property and use the Contains method to check.
Check the application status and record the PASS or FAIL results, I can easily exit the application to be tested:
Console.writeline ("/ nclicking menu file-> exit in 5 seconds..");
Thread.sleep (3500);
InvokeMethod ("Menuitem4_Click", New Object [] {null, new eventargs ();
Although the test application will terminate when test management is terminated because they are running in the same process, and the application to be tested is running in the background thread, but for any system resources allocated by explicit cleaning, the most It is ok to explicitly exit the application through test management. Back to top
discuss
If you want to implement UI test automation before .NET, it is actually only two options. First, buy commercial UI automation tools. Second, use the Microsoft Active Accessibility (MSAA) API to create its own UI automation tool. The system I introduced is well added to another two strategies. Several excellent commercial UI automation tools are available for you. The advantage of these tools is that they are fully functional. The disadvantage is that you need to pay for them, have a steep learning curve, and you do not allow you to access source code when you need to modify the function. Using MSAA allows you to fully control your automation tool, but it takes a long time to learn. In fact, in several projects I have done, MSAA-based UI test automation is likely to be as complex as the application to be tested!
The automation UI test method I mentioned here has been successfully used in several large and medium-sized products. Since it can be implemented quickly, it can be used in the product cycle when the test system is very unstable. However, since this UI test system is relatively lightweight, it cannot cope with all possible UI tests. You can use a variety of ways to modify and extend this design. Because the intention of this introduction is to have a preliminary understanding of the reader, in order to be clearer and simple, I delete most of the wrong checks and hardcodes most information. It is necessary to add a lot of error check code to test automation - after all, you are looking forward to finding errors.
Depending on your production environment, you can parameterize some parts of the test system. In terms of test terminology, the system I mentioned is called Test Scenario - a series of operations that control the status of the application to be tested (Different Cases (Test Case), the latter usually refers to a small operation, such as transmitting one Parameters give the method, check the return value.) For example, to parameterize the scheme, you can create a input file as shown below:
[set stat]
TextBox1: Text: Yellow
TextBox1: Text: Red
ComboBOBOX1: SELECTEDITEM: GREEN
ComboBox1: SelectedItem: Blue
Button1: Button1_Click
[Check State]
TextBox1: Text: Red
ComboBox1: SelectedItem: Blue
Listbox1: items: result is purple
Then you can automate your test automation read, resolve and use the data in this file. You can also use XML or SQL as the test scheme to enter data. The test system I introduced records its results into the command housing. You can easily redirect the results to a text file or rewrite automation through the command line, or rewrite automation.
The next generation of Windows will introduce a new representation subsystem that is "Avalon". Avalon will refer the UI test automation concept to a higher level. We need to provide platform-level support for all UI elements, and disclose the object model for all user controls. This allows developers and testers to quickly easily create extremely powerful UI test automation. The technique in this column is a prompt for revolutionary Avalon's work mode.
Before .NET, write automation is usually a very resource task, and test automation (especially UI test automation) is typically placed at the bottom of the product task priority list. However, after .Net, you only need to spend a small part of the time used, you can write very powerful test automation.
Please send you the questions and recommendations you want to James to Testrun@microsoft.com.
James McAffrey is responsible for technical training for software engineers working in Microsoft in Volt Information Sciences, Inc. He participated in developing a variety of Microsoft products, including Internet Explorer and MSN Search. You can get in touch with James with JMCAFFREY@volt.com or v-jammc@microsoft.com.
Go to the original English page
Copyright Notice: 9CBS is this BLOG managed service provider. If this paper involves copyright issues, 9CBS does not assume relevant responsibilities, please contact the copyright owner directly with the article Author.
[
Click here to favor this article]