.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,scissions

        7. 编译待测试程序,生成文件名为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,大功告成

原创粉丝点击