WinAppDriver 自动化测试winform程序

WinAppDriver 自动化测试winform程序

前言

WinAppDriver是Windows系统上的一个应用程序驱动工具,开源免费。与Selenium工具类似,都是用来实现产品UI自动化测试的一个工具。

WinAppDriver运行时对系统是有要求的,只能运行在Windows10或Windows Server 2016以上系统。如果测试程序兼容性,WinAppDriver很显然不能满足Windows10或Windows Server 2016以下系统的测试。因此使用WinAppDriver实现的自动化测试脚本是有局限性的。

WinAppDriver支持测试UWP、WinForms、WPF、Win32应用程序。

UWP: Universal Windows Platform,即Windows通用应用平台,在Windows 10 Mobile/Surface(Windows平板电脑)/PC/Xbox/HoloLens等平台上运行。它并不是为某一个终端而设计,而是可以在所有Windows10设备上运行。

WinForms: Windows Forms,是微软的.NET开发框架的图形用户界面部分,该组件通过将现有的Windows API(Win32 API)封装为托管代码提供了对Windows本地(native)组件的访问方式。

WPF: Windows Presentation Foundation,是微软推出的基Windows的用户界面框架,属于.NET Framework 3.0的一部分。它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的工作;同时它提供了全新的多媒体交互用户图形界面。

Win32: Classic Windows,是标准windows程序,完全拥有window的特性,可以通过鼠标点击窗口来完成控制。

在这里插入图片描述

1. 环境搭建

前提条件

电脑系统需要Windows 10或Windows Server 2016或者更高版本,这是前提条件

1.1 打开Windows PC的开发者模式

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1.2 下载Windows driver并安装

github下载地址:https://github.com/Microsoft/WinAppDriver/releases

在这里插入图片描述

选择与你电脑对应的exe安装

安装好之后,运行WinAppDriver.exe(记得要用admin权限运行), 默认路径 (C:\Program Files (x86)\Windows Application Driver)

也可以自定义地址或端口:
在cmd窗口中输入

WinAppDriver.exe 4727
WinAppDriver.exe 127.0.0.1 4725
WinAppDriver.exe 127.0.0.1 4723/wd/hub

在这里插入图片描述

在这里插入图片描述
这样就说明运行成功

2. Windows 自动化脚本

运行脚本前要打开 WinAppDriver.exe

对于Windows App来说,只需要传一个app capabilities 即可。

对于UWP的App,app对应的值为Application Id(App ID)。关于如何获取APP ID,可以使用powershell命令get-StartApps来获取,打开powershell终端运行:get-StartApps | select-string "计算器"即可获取值(运行命令之前先打开计算器)。

DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", CalculatorAppId);
appCapabilities.SetCapability("deviceName", "WindowsPC");
appCapabilities.SetCapability("platformName", "Windows");
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);

3. Windows定位元素

使用Windows SDK提供的工具inspect.exe(C:\Program Files (x86)\Windows Kits\10\bin\x86或者C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64根据系统查看)来定位,详情查看inspect,或者使用AccExplorer32、UISpy定位。
支持的定位方式:

在这里插入图片描述

4. 示例

这个是官方给的示例

CalculatorSession.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Remote;
using System;

namespace CalculatorTest
{
    public class CalculatorSession
    {
        // Note: append /wd/hub to the URL if you're directing the test at Appium
        private const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
        private const string CalculatorAppId = "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App";

        protected static WindowsDriver<WindowsElement> session;

        public static void Setup(TestContext context)
        {
            // Launch Calculator application if it is not yet launched
            if (session == null)
            {
                // Create a new session to bring up an instance of the Calculator application
                // Note: Multiple calculator windows (instances) share the same process Id
                DesiredCapabilities appCapabilities = new DesiredCapabilities();
                appCapabilities.SetCapability("app", CalculatorAppId);
                appCapabilities.SetCapability("deviceName", "WindowsPC");
                appCapabilities.SetCapability("platformName", "Windows");
                session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
                Assert.IsNotNull(session);

                // Set implicit timeout to 1.5 seconds to make element search to retry every 500 ms for at most three times
                session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1.5);
            }
        }

        public static void TearDown()
        {
            // Close the application and delete the session
            if (session != null)
            { 
                session.Quit();
                session = null;
            }
        }
    }
}

ScenarioStandard.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using System.Threading;
using System;

namespace CalculatorTest
{
    [TestClass]
    public class ScenarioStandard : CalculatorSession
    {
        private static WindowsElement header;
        private static WindowsElement calculatorResult;

        [TestMethod]
        public void Addition()
        {
            // Find the buttons by their names and click them in sequence to perform 1 + 7 = 8
            session.FindElementByName("一").Click();
            session.FindElementByName("加").Click();
            session.FindElementByName("七").Click();
            session.FindElementByName("等于").Click();
            Assert.AreEqual("8", GetCalculatorResultText());
        }

        [TestMethod]
        public void Division()
        {
            // Find the buttons by their accessibility ids and click them in sequence to perform 88 / 11 = 8
            session.FindElementByAccessibilityId("num8Button").Click();
            session.FindElementByAccessibilityId("num8Button").Click();
            session.FindElementByAccessibilityId("divideButton").Click();
            session.FindElementByAccessibilityId("num1Button").Click();
            session.FindElementByAccessibilityId("num1Button").Click();
            session.FindElementByAccessibilityId("equalButton").Click();
            Assert.AreEqual("8", GetCalculatorResultText());
        }

        [TestMethod]
        public void Multiplication()
        {
            // Find the buttons by their names using XPath and click them in sequence to perform 9 x 9 = 81
            //session.FindElementByXPath("//Button[@Name='Nine']").Click();
            //session.FindElementByXPath("//Button[@Name='Multiply by']").Click();
            //session.FindElementByXPath("//Button[@Name='Nine']").Click();
            //session.FindElementByXPath("//Button[@Name='Equals']").Click();


            session.FindElementByAccessibilityId("num9Button").Click();
            session.FindElementByAccessibilityId("num9Button").Click();
            session.FindElementByAccessibilityId("multiplyButton").Click();
            session.FindElementByAccessibilityId("num9Button").Click();
            session.FindElementByAccessibilityId("equalButton").Click();
            Assert.AreEqual("891", GetCalculatorResultText());
        }

        [TestMethod]
        public void Subtraction()
        {
            // Find the buttons by their accessibility ids using XPath and click them in sequence to perform 9 - 1 = 8
            session.FindElementByXPath("//Button[@AutomationId=\"num9Button\"]").Click();
            session.FindElementByXPath("//Button[@AutomationId=\"minusButton\"]").Click();
            session.FindElementByXPath("//Button[@AutomationId=\"num1Button\"]").Click();
            session.FindElementByXPath("//Button[@AutomationId=\"equalButton\"]").Click();
            Assert.AreEqual("8", GetCalculatorResultText());
        }

        [TestMethod]
        [DataRow("一",   "加",      "九", "10")]
        [DataRow("九",  "减",     "二",   "8")]
        [DataRow("八", "除以", "二", "4")]
        public void Templatized(string input1, string operation, string input2, string expectedResult)
        {
            // Run sequence of button presses specified above and validate the results
            session.FindElementByName(input1).Click();
            session.FindElementByName(operation).Click();
            session.FindElementByName(input2).Click();
            session.FindElementByName("等于").Click();
            Assert.AreEqual(expectedResult, GetCalculatorResultText());
        }

        [ClassInitialize]
        public static void ClassInitialize(TestContext context)
        {
            // Create session to launch a Calculator window
            Setup(context);

            // Identify calculator mode by locating the header
            try
            {
                header = session.FindElementByAccessibilityId("Header");
            }
            catch
            {
                header = session.FindElementByAccessibilityId("ContentPresenter");
            }            

            // Ensure that calculator is in standard mode
            if (!header.Text.Equals("标准", StringComparison.OrdinalIgnoreCase))
            {
                session.FindElementByAccessibilityId("TogglePaneButton").Click();
                Thread.Sleep(TimeSpan.FromSeconds(1));
                var splitViewPane = session.FindElementByClassName("SplitViewPane");
                splitViewPane.FindElementByName("标准").Click();
                Thread.Sleep(TimeSpan.FromSeconds(1));
                Assert.IsTrue(header.Text.Equals("标准", StringComparison.OrdinalIgnoreCase));
            }

            // Locate the calculatorResult element
            calculatorResult = session.FindElementByAccessibilityId("CalculatorResults");
            Assert.IsNotNull(calculatorResult);
        }

        [ClassCleanup]
        public static void ClassCleanup()
        {
            TearDown();
        }

        [TestInitialize]
        public void Clear()
        {
            session.FindElementByName("清除").Click();
            Assert.AreEqual("0", GetCalculatorResultText());
        }

        private string GetCalculatorResultText()
        {
            return calculatorResult.Text.Replace("显示为 ", string.Empty).Trim();
        }
    }
}

winform程序类似,先获取元素,然后模拟点击,输入框的模拟输入即可。

相关推荐

  1. Winform程序中UI更新延迟

    2024-04-10 14:30:03       17 阅读
  2. ubuntu中运行c# winform程序

    2024-04-10 14:30:03       10 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-10 14:30:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-10 14:30:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-10 14:30:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-10 14:30:03       18 阅读

热门阅读

  1. leetcode2529--正整数和负整数的最大计数

    2024-04-10 14:30:03       13 阅读
  2. vs2019不能创建控制台程序

    2024-04-10 14:30:03       12 阅读
  3. LeetCode热题100

    2024-04-10 14:30:03       9 阅读
  4. 联邦学习中的差分隐私与同态加密

    2024-04-10 14:30:03       13 阅读
  5. 渗透工具及其知识库(个人笔记)

    2024-04-10 14:30:03       11 阅读
  6. 程序员如何搞副业?

    2024-04-10 14:30:03       12 阅读
  7. 关于可视化大屏适配

    2024-04-10 14:30:03       13 阅读
  8. LeetCode 518. 零钱兑换 II

    2024-04-10 14:30:03       13 阅读
  9. 代码学习记录39---动态规划

    2024-04-10 14:30:03       11 阅读
  10. 由于等待端口使用超时,无法启动内核

    2024-04-10 14:30:03       13 阅读
  11. 【C语言】关键字选择题

    2024-04-10 14:30:03       11 阅读