在目前进行软件测试时,都或多或少的引入了自动化测试的概念,而且市面上也有好多软件自动化方面相关的工具,比如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,大功告成
————————————————
原文链接:https://blog.csdn.net/lassewang/article/details/6693917

.Net软件UI界面测试自动化--UIAutomation技术相关推荐

  1. 1.用Python写了一个进销存管理的软件~需求分析界面设计数据库设计技术路线选择~

    一.需求分析 总体来说,就是一个在游泳馆使用的进销存管理软件,记录商品的入库.出库情况,以及统计销售的金额等~ 整个系统有三类用户,系统管理员.公司管理员和公司销售员,系统管理员负责录入公司信息以及分 ...

  2. 安卓程序员都懂:如何用Espresso对UI界面测试?

    如果想学习使用Espresso测试Android应用程序UI,需要了解包括基础知识,AdapterViews,RecyclerViews等方面的知识,本文将是一份不错的教程. 作者写了关于Espres ...

  3. 微软搜索服务器,微软 Win10 搜索 UI 界面测试天气磁贴

    此前,用户在Windows 10 Insider版本中发现了适用于Windows Search搜索主屏幕的全新"天气"磁贴.现在,微软正在为Windows Search推出服务器端 ...

  4. winfrom软件开发汽车测试_ETci — 全自动软件测试调度(持续集成)平台

    ET·ci 提供了编译- 测试- 发布解决方案,包括:自动提取配置库代码进行自动构建, 自动调度静态测试工具(如QAC)进行静态测试,自动调度单元测试工具(如Tessy)开展动态测试,自动调度HIL ...

  5. Windows软件UI自动化测试之UiAutomation

    一.背景 最近在研究基于windows的UI自动化测试,通过自动化来解决重复.枯燥的人工点点点,目前支持Windows平台的UI自动化工具或框架比较多,比如:Autoit.pywinauto.UIau ...

  6. 《移动App测试实战》——2.2 App UI层面的自动化

    本节书摘来自华章出版社<移动App测试实战>一 书中的第2章,第2.2节,作者:邱鹏 陈吉 潘晓明,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2.2 Ap ...

  7. 软件自动化测试成功之道_是什么使测试自动化成功?

    软件自动化测试成功之道 测试是软件开发的一个重要但经常被低估的部分. 从定义上说,测试是具有挑战性的. 如果容易发现错误,那么它们就不会存在. 测试人员必须跳出框框思考,以发现其他人遗漏的错误. 在许 ...

  8. 基于深度学习的瓶子检测软件(UI界面+YOLOv5+训练数据集)

    摘要:基于深度学习的瓶子检测软件用于自动化瓶子检测与识别,对于各种场景下的塑料瓶.玻璃瓶等进行检测并计数,辅助计算机瓶子生产回收等工序.本文详细介绍深度学习的瓶子检测软件,在介绍算法原理的同时,给出P ...

  9. 【python】UI自动化-uiautomation

    UI自动化-uiautomation 0- 前言 1- inspect 2- uiautomation 3- [实战]RustDesk软件自动 安装.指定服务器信息 4- 参考文章 0- 前言 做应用 ...

最新文章

  1. java rpm_Java JDK rpm安装与配置
  2. UA MATH567 高维统计专题2 Low-rank矩阵及其估计3 Rank RIP
  3. mysql 日志的存放形式_mysql日志详细解析
  4. jzoj4228-C【dp】
  5. 《程序设计与数据结构》第3周学习总结
  6. c#调用c++dll接口及回调函数
  7. python多行语句_python多行语句
  8. Introduction to Real-Time Kernels
  9. 一个简单的fftw3例子:正弦信号的离散傅里叶变换
  10. 废品机械师双脚机器人教程_废品机械师自动寻物机器人图文教程_快吧单机游戏...
  11. asp系统转换php系统时间函数,window_Asp常用通用函数之生成时间的整数,'函数名:GetMyTimeNumber()' - phpStudy...
  12. Word中将传统的复选框型窗体域选项插件 批量替换成 复选框内容控件
  13. vue获取麦克风_vue使用recorder.js实现录音功能
  14. snagit 9注册码
  15. Spotfire调试经验——环比增长率的动态计算(Dynamic moving data percentage calculation in Spotfire visualization)
  16. crt链接linux后不能输入退格,SecureCRT 退格键等不好用
  17. WPS文档:格式显示,页码标注,公式居中编号右对齐,公式编号不能在行中间显示
  18. 使用ActiveX实现的Web自定义查询-万能查询
  19. C语言中静态变量的概念和用法
  20. 1.金融市场,资产管理与投资基金

热门文章

  1. OpenCV解码格雷码模式
  2. C语言实现链表栈 LinkedListStack(附完整源码)
  3. C++内存分配方式以及区别
  4. QT的QStringList类的使用
  5. QT的QMessageBox类的使用
  6. C/C++ 数据类型
  7. python 聚类算法包_Python聚类算法之DBSACN实例分析 python怎么用sklearn包进行聚类
  8. 「C++」C++ Primer Plus 笔记:第三章 处理数据
  9. sql优化之:数据库索引创建原则,or/in/union与索引优化,聚集索引/非聚集索引/联合索引/索引覆盖,MySQL冗余数据的三种方案,MySQL双主一致性架构优化(来源:架构师之路)
  10. 百度分享--分享按钮的实现