.Net软件UI界面测试自动化--UIAutomation技术
来源:互联网 发布:程序员笔记本推荐 编辑:程序博客网 时间:2024/06/03 03:38
在目前进行软件测试时,都或多或少的引入了自动化测试的概念,而且市面上也有好多软件自动化方面相关的工具,比如QTP,比如LoadRunner,但是这些工具要么售价不菲,要么对某些方面功能支持的不够全面,那么我们在引入软件自动化测试时,都需要考虑哪些方面呢?当然是最符合自己项目的工具最合适,同时费用也比较低,那么除了市面上这些商业软件外,还有没有哪些方法可以自己动手来做软件的自动化测试呢?答案是肯定的.
本文将介绍实现软件自动化测试其中一种测试方法------UIAutomation技术,当然,此种方法仅限于对.Net软件使用.
反射技术具体是什么原理,本文将不做任何介绍,大家可以去网上搜索一下,有很多这方面的文章介绍,本文只介绍如何使用UIAutomation技术进行.NET软件的UI界面的自动化测试.
废话少说,多做实事!(本文所有代码均在VS2008环境下测试通过)
一. 创建待测试程序
1. 启动VS2008,建立一个C#的WinForm工程,并将工程文件名命名为AUT(Application Under Test)
2. 创建的Form上的按钮布局,如下图所示
3. 一个菜单(包含一个以及菜单File以及一个二级菜单Exit),一个TextBox,一个ComboBox,一个Button以及一个ListBox
private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.ComboBox comboBox1; private System.Windows.Forms.Button button1; private System.Windows.Forms.ListBox listBox1;
4. 给Button按钮添加一个消息响应函数 private void button1_Click(object sender, EventArgs e) { string tb = textBox1.Text; string cb = comboBox1.Text; if (tb == cb) { listBox1.Items.Add("Result is a tie"); } else if (tb == "paper" && cb == "rock" || tb == "rock" && cb == "scissors" || tb == "scissors" && cb == "paper") { listBox1.Items.Add("The TextBox wins"); } else { listBox1.Items.Add("The ComboBox wins"); } }
5. 给Exit菜单添加一个消息响应函数 private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit(); }
6.给ComboBox控件添加三个Item,分别为paper,rock,scissions7. 编译待测试程序,生成文件名为AUT.exe的待测试程序
二. 创建测试程序
1. 启动VS2008,创建一个C#控制台程序,并命名为AutomationUITest
2. 在引用中添加以下三个类: UIAutomationClient, UIAutomationClientsideProviders以及UIAutomationTypes
3. 在工程中添加以下using语句
using System; using System.Windows.Automation; using System.Threading; using System.Diagnostics; using System.IO;
4. 定义启动测试程序以及获取窗体句柄的函数 ///<summary> ///根据传入的路径启动相应的可执行程序,并返回进程ID ///</summary> public static Int32 StartExe(string strExePath) { if (null == strExePath) { return 0; } Process ps = Process.Start(strExePath); Thread.Sleep(3000); return ps.Id; } ///<summary> ///根据进程ID,查找相应窗体,并返回窗体句柄 ///</summary> public static AutomationElement GetWindowHandle(Int32 pid, int iWaitSecond) { AutomationElement targetWindow = null; int iWaitTime = 0; try { Process ps = Process.GetProcessById(pid); targetWindow = AutomationElement.FromHandle(ps.MainWindowHandle); while (null == targetWindow) { if (iWaitTime > iWaitSecond) { break; } Thread.Sleep(500); targetWindow = AutomationElement.FromHandle(ps.MainWindowHandle); } return targetWindow; } catch (System.Exception ex) { string msg = "没有找到指定的窗口,请确认窗口已经启动!"; throw new InvalidProgramException(msg, ex); } }
5. 定义操作TextBox的相关函数\ ///<summary> ///根据窗口句柄以及TextEdit的AutomationID,返回TextEdit句柄 ///</summary> public static AutomationElement GetTextEditHandle(AutomationElement parentWindowHandle, string sAutomationID) { PropertyCondition condition = null; PropertyCondition codEdit = null; AndCondition andConditon = null; AutomationElement targetEditHandle = null; try { if (null == parentWindowHandle) { return null; } condition = new PropertyCondition(AutomationElement.AutomationIdProperty, sAutomationID); codEdit = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit); andConditon = new AndCondition(condition, codEdit); targetEditHandle = parentWindowHandle.FindFirst(TreeScope.Children, andConditon); return targetEditHandle; } catch (System.Exception ex) { string msg = "没有找到指定的TextEdit,请确认TextEdit的AutomationID是否正确!"; throw new InvalidProgramException(msg, ex); } } ///<summary> ///根据TextEdit句柄,在TextEdit内填写数据 ///只能设置单行输入的TextEdit ///</summary> public static bool SetTextEditData(AutomationElement TextEditHandle, string strData) { ValuePattern vpTextEdit = null; if (!TextEditHandle.Current.IsEnabled) { throw new InvalidOperationException("The control is not enabled.\n\n"); } if (!TextEditHandle.Current.IsKeyboardFocusable) { throw new InvalidOperationException("The control is not focusable.\n\n"); } vpTextEdit = TextEditHandle.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern; if (null == vpTextEdit) { return false; } if (vpTextEdit.Current.IsReadOnly) { throw new InvalidOperationException("The control is read-only."); } vpTextEdit.SetValue(strData); return true; }
6. 定义操作ComboBox的相关函数 ///<summary> ///根据窗口句柄以及ComboBox控件AutomationID,返回该ComboBox控件句柄 ///</summary> public static AutomationElement GetComboBoxHandle(AutomationElement parentWindowHandle, string sAutomationID) { AutomationElement ComboBoxHandle = null; PropertyCondition NameCondition = null; PropertyCondition TypeCondition = null; AndCondition andCondition = null; if (null == parentWindowHandle || null == sAutomationID) { return null; } NameCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, sAutomationID); TypeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ComboBox); andCondition = new AndCondition(NameCondition, TypeCondition); ComboBoxHandle = parentWindowHandle.FindFirst(TreeScope.Children, andCondition); if (null == ComboBoxHandle) { return null; } return ComboBoxHandle; } ///<summary> ///根据ComboBox控件句柄,设置数据 ///</summary> public static bool SetComboBoxItemData(AutomationElement ComboBoxHandle, string strData) { AutomationElement TextEditHandle = null; PropertyCondition TypeCondition = null; ValuePattern vpTextPattern = null; if (null == ComboBoxHandle || null == strData) { return false; } TypeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit); TextEditHandle = ComboBoxHandle.FindFirst(TreeScope.Children, TypeCondition); if (null == TextEditHandle) { return false; } if (!TextEditHandle.Current.IsEnabled) { throw new InvalidOperationException("The control is not enabled.\n\n"); } if (!TextEditHandle.Current.IsKeyboardFocusable) { throw new InvalidOperationException("The control is not focusable.\n\n"); } vpTextPattern = TextEditHandle.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern; if (null == vpTextPattern) { return false; } if (vpTextPattern.Current.IsReadOnly) { throw new InvalidOperationException("The control is read-only."); } vpTextPattern.SetValue(strData); return true; }
7. 定义操作Button的相关函数 ///<summary> ///根据窗口句柄以及Button的AutomationID,返回Button的句柄 ///</summary> public static AutomationElement GetButtonHandle(AutomationElement parentWindowHandle, string sAutomationID) { PropertyCondition condition = null; PropertyCondition codButton = null; AndCondition andConditon = null; AutomationElement targetButtonHandle = null; try { if (null == parentWindowHandle) { return null; } condition = new PropertyCondition(AutomationElement.AutomationIdProperty, sAutomationID); codButton = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button); andConditon = new AndCondition(condition, codButton); targetButtonHandle = parentWindowHandle.FindFirst(TreeScope.Children, andConditon); return targetButtonHandle; } catch (System.Exception ex) { string msg = "没有找到指定的按钮,请确认按钮AutomationID是否正确!"; throw new InvalidProgramException(msg, ex); } } ///<summart> ///根据Button按钮句柄,进行鼠标左键单击 ///</summary> public static bool ButtonLeftClick(AutomationElement ButtonHandle) { object objButton = null; InvokePattern ivkpButton = null; try { if (null == ButtonHandle) { return false; } if (!ButtonHandle.TryGetCurrentPattern(InvokePattern.Pattern, out objButton)) { return false; } ivkpButton = (InvokePattern)objButton; ivkpButton.Invoke(); return true; } catch (System.Exception ex) { string msg = "鼠标左键单击失败!"; throw new InvalidProgramException(msg, ex); } }
8. 定义操作ListBox的相关函数 ///<summary> ///根据窗口句柄以及ListBox控件AutomationID,返回该ListBox控件句柄 ///</summary> public static AutomationElement GetListBoxHandle(AutomationElement parentWindowHandle, string sAutomationID) { AutomationElement ListBoxHandle = null; PropertyCondition NameCondition = null; PropertyCondition TypeCondition = null; AndCondition andCondition = null; if (null == parentWindowHandle || null == sAutomationID) { return null; } NameCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, sAutomationID); TypeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.List); andCondition = new AndCondition(NameCondition, TypeCondition); ListBoxHandle = parentWindowHandle.FindFirst(TreeScope.Children, andCondition); if (null == ListBoxHandle) { return null; } return ListBoxHandle; } ///<summary> ///根据ListBox控件句柄以及ItemCount,选择该Item ///</summary> public static string GetListBoxItemName(AutomationElement ListBoxHandle, int iItemCount) { AutomationElementCollection ListBoxHandleCollection = null; PropertyCondition TypeCondition = null; if (null == ListBoxHandle || 0 > iItemCount) { return null; } TypeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem); ListBoxHandleCollection = ListBoxHandle.FindAll(TreeScope.Children, TypeCondition); if (null == ListBoxHandleCollection) { return null; } if (iItemCount >= ListBoxHandleCollection.Count) { return null; } return ListBoxHandleCollection[iItemCount].Current.Name; }
9. 定义操作菜单的相关函数 ///<summary> ///根据窗口句柄,以及MenuBar控件AutomationID,返回该MenuBar控件句柄 ///</summary> public static AutomationElement GetMenuBarHandle(AutomationElement parentWindow, string sAutomationID) { AutomationElement MBHandle = null; PropertyCondition NameCondition = null; PropertyCondition TypeCondition = null; AndCondition andCondition = null; if (null == parentWindow || null == sAutomationID) { return null; } NameCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, sAutomationID); TypeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.MenuBar); andCondition = new AndCondition(NameCondition, TypeCondition); MBHandle = parentWindow.FindFirst(TreeScope.Children, andCondition); if (null == MBHandle) { return null; } return MBHandle; } ///<summary> ///根据MenuBar控件句柄以及一级菜单名称,弹出一级菜单 ///</summary> private static AutomationElement PopupMenuBarItem(AutomationElement MBHandle, string FirMenuTitle) { InvokePattern IPMenu = null; AutomationElement MenuHandle = null; PropertyCondition NameCondition = null; PropertyCondition TypeCondition = null; AndCondition andCondition = null; if (null == MBHandle || null == FirMenuTitle) { return null; } NameCondition = new PropertyCondition(AutomationElement.NameProperty, FirMenuTitle); TypeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.MenuItem); andCondition = new AndCondition(NameCondition, TypeCondition); MenuHandle = MBHandle.FindFirst(TreeScope.Children, andCondition); if (null == MenuHandle) { return null; } IPMenu = MenuHandle.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern; if (null == IPMenu) { return null; } IPMenu.Invoke(); return MenuHandle; } ///<summary> ///根据MenuBar控件句柄以及传入的菜单名称,选择相应的菜单 ///传入的菜单名称,必须以空字符串结束 ///</summary> public static bool SelectMenuBarItem(AutomationElement MBHandle, string[] strTitle) { AutomationElement MenuItemHandle = null; MenuItemHandle = MBHandle; foreach (string str in strTitle) { if ("" == str) { break; } MenuItemHandle = PopupMenuBarItem(MenuItemHandle, str); if (null == MenuItemHandle) { return false; } Thread.Sleep(400); } return true; }
10. 添加测试代码 static void Main(string[] args) { string path = Directory.GetCurrentDirectory() + "\\AUT.exe"; try { Console.WriteLine("\nStart Application Under Test Exe"); Int32 ProcessId = StartExe(path); Console.WriteLine("Application Under Test ProcessID: " + ProcessId.ToString()); Console.WriteLine("\nGet Main Window Handle"); AutomationElement mwh = GetWindowHandle(ProcessId, 3000); Console.WriteLine("Main Window Handle: " + mwh.Current.NativeWindowHandle.ToString()); Console.WriteLine("\nGet TextBox Handle"); AutomationElement tbh = GetTextEditHandle(mwh, "textBox1"); Console.WriteLine("TextBox Handle: " + tbh.Current.NativeWindowHandle.ToString()); Console.WriteLine("\nGet ComboBox Handle"); AutomationElement cbh = GetComboBoxHandle(mwh, "comboBox1"); Console.WriteLine("ComboBox Handle: " + cbh.Current.NativeWindowHandle.ToString()); Console.WriteLine("\nGet Button Handle"); AutomationElement bth = GetButtonHandle(mwh, "button1"); Console.WriteLine("Button Handle: " + bth.Current.NativeWindowHandle.ToString()); Console.WriteLine("\nGet ListBox Handle"); AutomationElement lbh = GetListBoxHandle(mwh, "listBox1"); Console.WriteLine("ListBox Handle: " + lbh.Current.NativeWindowHandle.ToString()); Console.WriteLine("\nSet TextBox Value"); SetTextEditData(tbh, "paper"); Console.WriteLine("\nSet ConboxBox Value"); SetComboBoxItemData(cbh, "rock"); Console.WriteLine("\nPush Mouse Left button"); ButtonLeftClick(bth); string result = GetListBoxItemName(lbh, 0); if (result == "The TextBox wins") { Console.WriteLine("\nTest seceions = PASS"); } else { Console.WriteLine("\nTest seceions = Failed"); } Console.WriteLine("\nGet Menu Handle"); AutomationElement mbh = GetMenuBarHandle(mwh, "menuStrip1"); Console.WriteLine("Menu Handle: " + mbh.Current.NativeWindowHandle.ToString()); string[] strTitle = { "File", "Exit", "" }; Console.WriteLine("\nClose Application Under Test in 3 Seconds...."); Thread.Sleep(3000); SelectMenuBarItem(mbh, strTitle); Console.ReadLine(); } catch (System.Exception ex) { Console.WriteLine("\nError msg: " + ex.Message); } }
11. 编译测试程序,OK,大功告成- .Net软件UI界面测试自动化--UIAutomation技术
- .Net软件UI界面测试自动化--反射技术
- .Net软件UI界面测试自动化--Windows API
- iOS --- 自动化测试工具UIAutomation
- iOS自动化测试之UIAutomation
- iOS自动化测试与uiautomation
- 使用UIAutomation进行 iOS 自动化测试
- IOS自动化测试之UIAutomation学习
- IOS自动化测试化UIAutomation(一)
- 如何使用UIAutomation进行iOS 自动化测试
- 如何利用 UIAutomation 自动化测试 iOS 应用
- 如何使用UIAutomation进行iOS 自动化测试
- IOS自动化测试之UIAutomation学习
- UIAutomation---IOS自动化测试的工具
- 用python进行应用程序自动化测试(uiautomation)
- 跟UI自动化测试有关的技术
- 微软UI自动化测试的技术演变
- 【搜狗测试】iOS自动化测试之UIAutomation
- The Story
- 2种方法求解约瑟夫环问题
- Java程序报:Target runtime Apache Tomcat v5.5 is not defined .
- 在线文本编辑器(四)——整合前的一些修改
- HTTP头标
- .Net软件UI界面测试自动化--UIAutomation技术
- jsp中跳转 jsp的两种跳转方式及区别
- 用Eclipse编译Spring-Security3
- ALSA 音频驱动简要解析
- 多线程切换View时线程不同步的问题---游戏状态跳转管理
- 人际关系经验<绝对受用>
- 笛卡尔树
- MSTR如何通过实体实现SQL中的连接查询
- 简单的冒泡排序,你能做对吗?