基于C#UI Automation自动化测试

这篇具有很好参考价值的文章主要介绍了基于C#UI Automation自动化测试。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

步骤

UI Automation 只适用于,标准的win32和 WPF程序

c# 自动化测试,C#,自动化测试,UIAVerify,C#

c# 自动化测试,C#,自动化测试,UIAVerify,C#

c# 自动化测试,C#,自动化测试,UIAVerify,C#

c# 自动化测试,C#,自动化测试,UIAVerify,C#

c# 自动化测试,C#,自动化测试,UIAVerify,C#

c# 自动化测试,C#,自动化测试,UIAVerify,C#

需要添加对UIAutomationClient、 UIAutomationProvider、 UIAutomationTypes的引用

c# 自动化测试,C#,自动化测试,UIAVerify,C#

代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Automation;
using System.Windows.Forms;
using System.Windows.Input;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private Process processnotepad;
        private Process processcalc;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //打开笔记本
            processnotepad = Process.Start(@"C:\Windows\System32\notepad.exe");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //关闭笔记本
            processnotepad.Kill();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //AutomationElement表示 UI 自动化树中的一个 UI 自动化元素,并包含由 UI 自动化客户端应用程序用作标识符的值。
            //获取当前桌面的根 AutomationElement。
            AutomationElement desktop = AutomationElement.RootElement;
            //StringBuilder不在内存中创建新对象,而是动态扩展内存以容纳修改后的字符串。
            StringBuilder sb = new StringBuilder();
            //TreeScope(枚举)包含指定 UI 自动化目录树内元素的范围的值。具体参考请点击以下链接进行查看
            //TreeScope官方链接:https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.automation.treescope?view=windowsdesktop-7.0
            AutomationElementCollection topWindows = desktop.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));//查找计算器
            for (int i = 0; i < topWindows.Count; i++)
            {
                AutomationElement topWindow = topWindows[i];
                sb.AppendLine("Name:" + topWindow.Current.Name + ";ClassName=" + topWindow.Current.ClassName);
            }
            MessageBox.Show(sb.ToString());
        }

        private void button4_Click(object sender, EventArgs e)
        {
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));
            AutomationElementCollection btn2 = calcFrame1.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "num9Button"));
            AutomationElement btn = btn2[0];
            MessageBox.Show(btn.Current.Name);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));

            Condition conditionBtn6 = new AndCondition(
                new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),
                new PropertyCondition(AutomationElement.NameProperty, "六")
                );
            var btn6 = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn6);
            //InvokePattern 表示用于启动或执行单个明确操作的控件,并且这些控件在激活时不保持其状态。
            //InvokePattern.Pattern 标识 InvokePattern 控件模式。
            //InvokePattern官方链接 https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.automation.invokepattern?view=windowsdesktop-7.0
            InvokePattern button6Invoke = (InvokePattern)btn6.GetCurrentPattern(InvokePattern.Pattern);
            //Invoke() 发送请求以激活控件并启动其单一、明确的操作。
            button6Invoke.Invoke();

            

            Condition conditionBtnPlus = new AndCondition(
           new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),
           new PropertyCondition(AutomationElement.NameProperty, "加")
           );
            var btnPlus = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtnPlus);
            InvokePattern buttonPlusInvoke = (InvokePattern)btnPlus.GetCurrentPattern(InvokePattern.Pattern);
            buttonPlusInvoke.Invoke();
        }
        private static void InvokeButton(AutomationElement e)
        {
            InvokePattern Invoke = (InvokePattern)e.GetCurrentPattern(InvokePattern.Pattern);
            Invoke.Invoke();
        }
        private static void ClickCalculatorButton(AutomationElement calcFrame1, String name)
        {
            Condition conditionBtn = new AndCondition(
               new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),
               new PropertyCondition(AutomationElement.NameProperty, name)
               );
            var btn = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn);
            // MessageBox.Show(btn.Current.Name);
            if (btn == null)
            {
                throw new Exception("找不到此" + name + "的按钮");
            }
            InvokeButton(btn);
        }

        private void button6_Click(object sender, EventArgs e)
        {
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));
            ClickCalculatorButton(calcFrame1, "三");
            ClickCalculatorButton(calcFrame1, "乘以");
            ClickCalculatorButton(calcFrame1, "五");
            ClickCalculatorButton(calcFrame1, "五");
            ClickCalculatorButton(calcFrame1, "等于");
        }

        [DllImport("user32.dll")]
        public static extern void SetCursorPos(int x, int y);

        [DllImport("user32.dll")]
        public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);


        private void button7_Click(object sender, EventArgs e)
        {
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));

            Condition conditionBtn6 = new AndCondition(
                new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),
                new PropertyCondition(AutomationElement.NameProperty, "六")
                );
            var btn6 = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn6);

            SetCursorPos((int)btn6.GetClickablePoint().X, (int)btn6.GetClickablePoint().Y);
            //mouse_event(0x0002 | 0x0004, 0, 0, 0, 0);
            mouse_event(0x0002, 0, 0, 0, 0);  // 模拟鼠标左键按下
            mouse_event(0x0004, 0, 0, 0, 0);  // 模拟鼠标左键弹起

        }



        private void button8_Click(object sender, EventArgs e)
        {
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));

            Condition conditionEdit = new AndCondition( 
                new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"), new PropertyCondition(AutomationElement.NameProperty, "文本编辑器"));
            AutomationElement txtEdit = calcFrame1.FindFirst(TreeScope.Descendants, conditionEdit);
            txtEdit.SetFocus();
            SendKeys.Send("追加123456789");
        }

        private const int WM_SETTEXT = 0x000C;

        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll")]
        private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindows);

        [DllImport("User32.dll")]
        private static extern Int32 SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, StringBuilder lParam);

        private void button9_Click(object sender, EventArgs e)
        {
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));

            Condition conditionEdit = new AndCondition(
                new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"), new PropertyCondition(AutomationElement.NameProperty, "文本编辑器"));
            AutomationElement txtEdit = calcFrame1.FindFirst(TreeScope.Descendants, conditionEdit);
            //.NET提供了一个结构体System.IntPtr专门用来代表句柄或指针。
            //句柄是对象的标识符,当调用这些API创建对象时,它们并不直接返回指向对象的指针,
            //而是会返回一个32位或64位的整数值,这个在进程或系统范围内唯一的整数值就是句柄(Handle),
            //随后程序再次访问对象,或者删除对象,都将句柄作为Windows API的参数来间接对这些对象进行操作。
            //句柄是一个结构体,简单的来说,它是指针的一个封装,是C#中指针的替代者
            //句柄链接:https://blog.csdn.net/sinat_40003796/article/details/127244155
            IntPtr hWnd = FindWindow("Notepad", null);
            if (!hWnd.Equals(IntPtr.Zero))
            {
                IntPtr edithWnd = FindWindowEx(hWnd, IntPtr.Zero, "Edit", null);
                if (!edithWnd.Equals(IntPtr.Zero))
                {
                    SendMessage(edithWnd, WM_SETTEXT, IntPtr.Zero, new StringBuilder("重写123456789"));
                }
            }
            else
            {
            }

        }

        private void button10_Click(object sender, EventArgs e)
        {
            //点击后有列表的按钮不要当成点击事件
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
            Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, "编辑(E)");
            AutomationElement w2 = calcFrame1.FindFirst(TreeScope.Descendants, myCondition2);
            ExpandCollapsePattern ecp = (ExpandCollapsePattern)w2.GetCurrentPattern(ExpandCollapsePattern.Pattern);
            ecp.Expand();
        }

        private AutomationElement autoElementGet1(AutomationElement e, string s)
        {
            Condition myCondition1 = new PropertyCondition(AutomationElement.AutomationIdProperty, s);
            Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, s);
            Condition myCondition3 = new PropertyCondition(AutomationElement.AcceleratorKeyProperty, s);
            Condition myCondition4 = new PropertyCondition(AutomationElement.ClassNameProperty, s);
            Condition myCondition5 = new PropertyCondition(AutomationElement.AccessKeyProperty, s);
            Condition myCondition6 = new PropertyCondition(AutomationElement.LocalizedControlTypeProperty, s);
            Condition myCondition = new OrCondition(myCondition1, myCondition2, myCondition3, myCondition4, myCondition5,
                myCondition6);
            AutomationElementCollection myCollection = e.FindAll(TreeScope.Descendants, myCondition);
            return myCollection[0];
        }
        private void button11_Click(object sender, EventArgs e)
        {
            //随机元素获取
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
            AutomationElement filename = autoElementGet1(calcFrame1, "文件(F)");
            MessageBox.Show("Name:" + filename.Current.Name + ";ClassName=" + filename.Current.ClassName);
        }

        private void button12_Click(object sender, EventArgs e)
        {
            //遍历子控件
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
            Condition myCondition1 = new PropertyCondition(AutomationElement.AutomationIdProperty, "MenuBar");
            AutomationElement MenuBar = calcFrame1.FindFirst(TreeScope.Descendants, myCondition1);
            AutomationElementCollection MenuBarChildAll = MenuBar.FindAll(TreeScope.Children, Condition.TrueCondition);
            for (int i = 0; i < MenuBarChildAll.Count; i++)
            {
                AutomationElement MenuBarChild = MenuBarChildAll[i];
                MessageBox.Show("Name:" + MenuBarChild.Current.Name + ";ClassName=" + MenuBarChild.Current.ClassName + ";ControlType=" + MenuBarChild.Current.ControlType);
            }


        }

        private void button13_Click(object sender, EventArgs e)
        {
            processcalc = Process.Start(@"C:\Windows\System32\calc.exe");
        }

        private void button14_Click(object sender, EventArgs e)
        {
            processcalc.Kill();
        }

        private void button15_Click(object sender, EventArgs e)
        {
            //点击后有列表的按钮不要当成点击事件
            AutomationElement desktop = AutomationElement.RootElement;
            var calcFrame1 = desktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
            Condition myCondition1 = new PropertyCondition(AutomationElement.NameProperty, "文件(F)");
            AutomationElement w1 = calcFrame1.FindFirst(TreeScope.Descendants, myCondition1);
            ExpandCollapsePattern ecp = (ExpandCollapsePattern)w1.GetCurrentPattern(ExpandCollapsePattern.Pattern);
            ecp.Expand();
            Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, "退出(X)");
            AutomationElementCollection myCollection = w1.FindAll(TreeScope.Descendants, myCondition2);
            AutomationElement w2 = myCollection[0];
            InvokePattern ipn = (InvokePattern)w2.GetCurrentPattern(InvokePattern.Pattern);
            ipn.Invoke();
            Thread.Sleep(500);
            AutomationElement savefile = calcFrame1.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "保存(S)"));
            if (savefile != null)
            {
                InvokePattern savefilebutton = (InvokePattern)savefile.GetCurrentPattern(InvokePattern.Pattern);
                savefilebutton.Invoke();
                Thread.Sleep(500);
                AutomationElement Saveasform = calcFrame1.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "另存为"));
                AutomationElement edit1 = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "1001"));
                ValuePattern vp = (ValuePattern)edit1.GetCurrentPattern(ValuePattern.Pattern);
                vp.SetValue("aaa.txt");
                AutomationElement savefilepath = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "保存(S)"));
                InvokePattern savefilepathbutton = (InvokePattern)savefilepath.GetCurrentPattern(InvokePattern.Pattern);
                savefilepathbutton.Invoke();
                Thread.Sleep(500);
                AutomationElement yesSaveasform = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "确认另存为"));
                AutomationElement issavefilepath = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "是(Y)"));
                if (issavefilepath != null) {
                    InvokePattern issavefilepathbutton = (InvokePattern)issavefilepath.GetCurrentPattern(InvokePattern.Pattern);
                    issavefilepathbutton.Invoke();
                }
            }
            

        }
    }
}

各按钮的功能展示

打开记事本

c# 自动化测试,C#,自动化测试,UIAVerify,C#

关闭记事本

c# 自动化测试,C#,自动化测试,UIAVerify,C#

获取计算器窗体

修改对应代码,每个按钮点击事件下的的该属性都需要进行修改

c# 自动化测试,C#,自动化测试,UIAVerify,C# 结果

c# 自动化测试,C#,自动化测试,UIAVerify,C#

获取控件属性

c# 自动化测试,C#,自动化测试,UIAVerify,C#

c# 自动化测试,C#,自动化测试,UIAVerify,C#

 结果c# 自动化测试,C#,自动化测试,UIAVerify,C#

点击按钮

c# 自动化测试,C#,自动化测试,UIAVerify,C#

完成计算器计算

c# 自动化测试,C#,自动化测试,UIAVerify,C#

 鼠标点击按钮

功能是让鼠标去点击,实现点击按钮的功能

c# 自动化测试,C#,自动化测试,UIAVerify,C#

 追加记事本内容

原始

c# 自动化测试,C#,自动化测试,UIAVerify,C#

运行

c# 自动化测试,C#,自动化测试,UIAVerify,C#

 重写记事本内容

c# 自动化测试,C#,自动化测试,UIAVerify,C#

展开按钮列表

c# 自动化测试,C#,自动化测试,UIAVerify,C#

随机获取元素方法

c# 自动化测试,C#,自动化测试,UIAVerify,C#

遍历记事本菜单栏

c# 自动化测试,C#,自动化测试,UIAVerify,C#

打开计算器

c# 自动化测试,C#,自动化测试,UIAVerify,C#

控件关闭计算器

c# 自动化测试,C#,自动化测试,UIAVerify,C#

 保存记事本

c# 自动化测试,C#,自动化测试,UIAVerify,C#

工程示例

https://download.csdn.net/download/qq_39397927/88215681

参考

https://www.cnblogs.com/baihuitestsoftware/articles/9047705.html

UI自动化 --- 微软UI Automation_dotNET跨平台的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-775314.html

到了这里,关于基于C#UI Automation自动化测试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • selenium-基于UI的自动化测试框架

      自动化测试是指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最后评估运行结果,将人为驱动的测试行为转化为机器执行的过程   自动化测试包括UI自动化、接口自动化、单元测试自动化。按照这个金字塔模型来进行自动化测试

    2024年02月05日
    浏览(59)
  • 基于 Appium 的 Android UI 自动化测试!

    自动化测试是研发人员进行质量保障的重要一环,良好的自动化测试机制能够让开发者及早发现编码中的逻辑缺陷,将风险前置。日常研发中,由于快速迭代的原因,我们经常需要在各个业务线上进行主流程回归测试,目前这种测试大部分由人工进行,费时费力,重复劳动多

    2024年02月08日
    浏览(59)
  • 基于图片识别的 UI 自动化测试工具 SikuliX

    简介 SikuliX 是一款开源的 GUI自动化测试工具,它的前身是 Sikuli(上帝之眼).SikuliX 在设计上使用到了图片识别技术,会通过不停的对桌面进行截图,然后与预期图片进行比较来判断交互条件.因此我们可以很方便的通过定义图片来设置交互条件如下: 上面就是通过SikuliX实现的一个简

    2024年02月01日
    浏览(56)
  • 基于Selenium和python的UI自动化测试方案

    对于比较复杂的系统,每次有小的迭代测试同学不可能会把所有的流程验证一遍,如果开发无意改动影响了某些流程而测试又没测试到,就可能会出现生产问题,因此很有必要通过自动化的测试去确保系统的稳定性。自动化测试可以选择接口自动化测试和UI自动化测试,从复

    2024年02月04日
    浏览(45)
  • 基于web应用的UI自动化、跨浏览器测试、测试结果分析:Selenium 开源的自动化测试工具基础教程

    作者:禅与计算机程序设计艺术 Selenium是一个开源的自动化测试工具,它提供了基于web应用的UI自动化、跨浏览器测试、测试结果分析等功能。它提供的功能包括:自动化控制浏览器、操纵表单、点击链接及按钮、验证页面元素、执行JavaScript代码、生成PDF文件、模拟移动设备

    2024年02月09日
    浏览(49)
  • Selenium——基于Web的UI自动化测试工具(一)

            Selenium是一个自动化测试工具,用于模拟用户在Web上的行为。它支持多种浏览器,如Chrome、Firefox、IE等。Selenium可以实现多种操作,包括打开浏览器、导航到指定URL、填写表单、点击按钮、获取页面元素等。         Selenium有多种语言实现,包括Java、Python、C#等

    2024年04月13日
    浏览(50)
  • 基于Selenium的Web UI自动化测试框架开发实战

    1、自研自动化测试框架 首先进行需求分析。概要设计包括以下三大模块: 公共函数库模块(包括可复用函数库、日志管理、报表管理及发送邮件管理); 测试用例仓库模块(具体用例的相关管理); 可视化页面管理模块(单独针对Web页面进行抽象,封装页面元素和操作方

    2024年01月20日
    浏览(71)
  • 基于Python+Pytest+Playwright+BDD的UI自动化测试框架

    本框架是基于Python+Pytest+Playwright+BDD的UI自动化测试框架。 测试社区地址: https://www.gitlink.org.cn/zone/tester 入群二维码:https://www.gitlink.org.cn/floraachy/apiautotest/issues/1 对于框架任何问题,欢迎联系我! 支持通过命令行指定浏览器,选择需要运行的浏览器。 支持通过命令行指定运行

    2024年02月07日
    浏览(56)
  • 基于Flutter的一款摸鱼APP的UI自动化测试实践

    最近想在全网找一个好用的摸鱼app,为了上班时摸摸鱼,毕竟一直摸鱼一直爽嘛。对比了网上几款摸鱼软件,最终选择这款应用——摸鱼kik。以往所用的RSS订阅在摸鱼kik中发挥到了极致,我们既可以订阅感兴趣的内容,也可以“二次聚合”我们想要的信息。 给大家截了几张图

    2023年04月11日
    浏览(45)
  • 基于 HttpRunner + Django + Vue + Element UI 的接口自动化测试平台

    https://github.com/tahitimoon/LunarLink https://lunar-link-docs.fun 基于HttpRunner + Django + Vue + Element UI 的接口自动化测试平台,生产可用。 此外,非常感谢 花菜。没有 AnotherFasterRunner 就不会有 LunarLink 😃 🎨 Django 🎶 Django Rest framework 🎉 Vue.js 🎃 Element UI 🏐 django-celery-beat(定时任务) 🎲

    2024年04月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包