• 使用UI Automation实现自动化测试7.1 (模拟键盘输入数据在自动化测试中的应用)


    Chapter 7 Simulated keyboard

     

    7.1 模拟键盘输入

    7.1.1 Introduction

    此部分我们通过System.Windows.Forms.SendKeys类中的Send方法来模拟通过键盘输入数据到相应的控件中。

    7.1.2 SendKeys Class IntroductionMSDN

    使用 SendKeys 将键击和组合键击发送到活动应用程序。此类无法实例化。若要发送一个键击给某个类并立即继续程序流,请使用 Send。若要等待键击启动的任何进程,请使用 SendWait

    每个键都由一个或多个字符表示。若要指定单个键盘字符,请使用该字符本身。例如,若要表示字母 A,请将字符串“A”传递给方法。若要表示多个字符,请将各个附加字符追加到它之前的字符的后面。若要表示字母 AB C,请将参数指定为“ABC”

    加号 (+)、插入符号 (^)、百分号 (%)、波浪号 (~) 以及圆括号 ( ) SendKeys 具有特殊含义。若要指定这些字符中的某个字符,请将其放在大括号 ({}) 内。例如,若要指定加号,请使用“{+}”。若要指定大括号字符,请使用“{{}”“{}}”。中括号 ([ ]) SendKeys 没有特殊含义,但必须将它们放在大括号内。在其他应用程序中,中括号具有特殊含义,此含义可能会在发生动态数据交换 (DDE) 时起重要作用。

    7.1.3 SendKeys MethodMSDN

    SendKeys有两个重要的方法:

    1.         Send方法:向活动应用程序发送击键。 

    2.         SendWait方法:向活动应用程序发送给定的键,然后等待消息被处理。 

    有关SendKeys的参考:

    英文站点:http://msdn.microsoft.com/en-us/library/8c6yea83(VS.85).aspx

    中文站点:http://msdn.microsoft.com/zh-cn/library/system.windows.forms.sendkeys_methods(VS.80).aspx

     

        下面我们通过一个实例来演示通过SendKeys类来模拟键盘操作进行数据输入和快捷菜单的打开:

    using System;

    using System.Text;

    using System.Diagnostics;

    using System.Threading;

    using System.Windows.Automation;

    using System.Runtime.InteropServices;

    using System.Windows;

    using System.Windows.Forms;

     

    namespace UIATest

    {

        class Program

        {

            static void Main(string[] args)

            {

                Process process = Process.Start(@"E:\WorkBook\ATP\WpfApp\bin\Debug\WpfApp.exe");

                int processId = process.Id;

     

                AutomationElement element = FindElementById(processId, "textBox1");

                SendKeys sendkeys = new SendKeys();

                sendkeys.Sendkeys(element, "Sending keys to input data");

                Console.WriteLine(sendkeys.ToString());

                sendkeys.Sendkeys(element, sendkeys.ContextMenu);

                Console.WriteLine(sendkeys.ToString());

                Console.WriteLine("Test finised.");  

            }

     

            /// <summary>

            /// Get the automation elemention of current form.

            /// </summary>

            /// <param name="processId">Process Id</param>

            /// <returns>Target element</returns>

            public static AutomationElement FindWindowByProcessId(int processId)

            {

                AutomationElement targetWindow = null;

                int count = 0;

                try

                {

                    Process p = Process.GetProcessById(processId);

                    targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);

                    return targetWindow;

                }

                catch (Exception ex)

                {

                    count++;

                    StringBuilder sb = new StringBuilder();

                    string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();

                    if (count > 5)

                    {

                        throw new InvalidProgramException(message, ex);

                    }

                    else

                    {

                        return FindWindowByProcessId(processId);

                    }

                }

            }

     

            /// <summary>

            /// Get the automation element by automation Id.

            /// </summary>

            /// <param name="windowName">Window name</param>

            /// <param name="automationId">Control automation Id</param>

            /// <returns>Automatin element searched by automation Id</returns>

            public static AutomationElement FindElementById(int processId, string automationId)

            {

                AutomationElement aeForm = FindWindowByProcessId(processId);

                AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,

                new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));

                return tarFindElement;

            }

        }

    }

          我们自定义一个SendKeys类来对已有的SendKeys类进行优化,代码如下:

    using System;

    using System.Windows.Automation;

    using System.Threading;

    using System.Text;

    using System.Windows.Forms;

     

    namespace UIATest

    {

        public class SendKeys

        {

            StringBuilder builder = new StringBuilder();

     

            public string Alt = "%";

            public string ContextMenu = "+{F10}";

            public string Ctrl = "^";

            public string Shift = "+";

            public string Enter = "{Enter}";

            public string Delete = "{Del}";

            public string Save = "^S";

            public string SaveAll = "^+S";

            public string Copy = "^C";

            public string Cut = "^X";

            public string Paste = "^V";

            public string Undo = "^Z";

            public string Redo = "^Y";

            public string Print = "^P";

            public string Help = "{F1}";

            public string New = "^N";

     

            public string[] Keys{ get; set; }

     

     

            public void Sendkeys(AutomationElement element, string[] keys)

            {

                this.Keys = keys;

                try

                {

                    element.SetFocus();

                }

                catch (Exception exception)

                {

                    throw new Exception("Cannot set focus to this element.", exception);

                }

                string myKeys = "";

                foreach (string str2 in this.Keys)

                {

                    myKeys = myKeys + str2;

                }

                Thread.Sleep(200);

                if ((this.ContainsUnescapedKey(myKeys, '^') || this.ContainsUnescapedKey(myKeys, '%')) || this.ContainsUnescapedKey(myKeys, '+'))

                {

                    myKeys = myKeys.ToLower();

                }

                System.Windows.Forms.SendKeys.SendWait(myKeys);

                Thread.Sleep(0x3e8);

            }

     

            public void Sendkeys(AutomationElement element, string myKeys)

            {

                this.Keys = new string[1];

                this.Keys[0] = myKeys;

                try

                {

                    element.SetFocus();

                }

                catch (Exception exception)

                {

                    throw new Exception("Cannot set focus to this element.", exception);

                }

                Thread.Sleep(200);

                if ((this.ContainsUnescapedKey(myKeys, '^') || this.ContainsUnescapedKey(myKeys, '%')) || this.ContainsUnescapedKey(myKeys, '+'))

                {

                    myKeys = myKeys.ToLower();

                }

                System.Windows.Forms.SendKeys.SendWait(myKeys);

                Thread.Sleep(0x3e8);

            }

           

            private bool ContainsUnescapedKey(string keys, char key)

            {

                for (int i = 0; i < keys.Length; i++)

                {

                    if (keys[i] == key)

                    {

                        if ((i == 0) || (i == (keys.Length - 1)))

                        {

                            return true;

                        }

                        if ((keys[i - 1] != '{') || (keys[i + 1] != '}'))

                        {

                            return true;

                        }

                    }

                }

                return false;

            }

     

            private string KeysToString(string[] keys)

            {

               

                if (keys != null)

                {

                    for (int i = 0; i < keys.Length; i++)

                    {

                        string str = keys[i];

                        if (str == null)

                        {

                            builder.Append(keys[i]);

                        }

                        int length = keys.Length - 1;

                        switch (str)

                        {

                            case "^":

                                builder.Append("Ctrl");

                                IsEquals(i, length, builder);

                                break;

                            case "+{F10}":

                                builder.Append("Open Context Menu");

                                IsEquals(i, length, builder);

                                break;

                            case "%":

                                builder.Append("Alt");

                                IsEquals(i, length, builder);

                                break;

                            case "+":

                                builder.Append("Shift");

                                IsEquals(i, length, builder);

                                break;

                            case "^S":

                                builder.Append("Save");

                                IsEquals(i, length, builder);

                                break;

                            case "^X":

                                builder.Append("Cut");

                                IsEquals(i, length, builder);

                                break;

                            case "^C":

                                builder.Append("Copy");

                                IsEquals(i, length, builder);

                                break;

                            case "^V":

                                builder.Append("Paste");

                                IsEquals(i, length, builder);

                                break;

                            case "^+S":

                                builder.Append("Save All");

                                IsEquals(i, length, builder);

                                break;

                            case "^P":

                                builder.Append("Print");

                                IsEquals(i, length, builder);

                                break;

                            case "^Z":

                                builder.Append("Undo");

                                IsEquals(i, length, builder);

                                break;

                            case "^Y":

                                builder.Append("Redo");

                                IsEquals(i, length, builder);

                                break;

                            case "^N":

                                builder.Append("New");

                                IsEquals(i, length, builder);

                                break;

                            default:

                                builder.Append(keys[i]);

                                IsEquals(i, length, builder);

                                break;

                        }

                    }

                }

                return builder.ToString();

            }

     

            void IsEquals(int i, int length, StringBuilder builder)

            {

                if(i<length)

                    builder.Append("+");

            }

               

            #region Public Method

     

            public override string ToString()

            {

                return string.Format("Sendkeys to input data or operator with keys = '{0}'",

                    this.KeysToString(Keys));

            }

            #endregion

        }

    }

        如下代码为对应的WPF窗体XAML代码:

    <Window x:Class="WpfApp.SendKeysInputData"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="SendKeysInputData" Height="250" Width="367">

        <Grid>

            <TextBox Margin="28,80,41,101" Name="textBox1">

                <TextBox.ContextMenu>

                    <ContextMenu>

                        <MenuItem Header="Open" />

                        <MenuItem Header="Save" />

                        <MenuItem Header="New" />

                        <MenuItem Header="Save As" />

                        <MenuItem Header="Load" />

                        <MenuItem Header="ReLoad" />

                    </ContextMenu>

                </TextBox.ContextMenu>

            </TextBox>

        </Grid>

    </Window>

    7.1.4 Summary

    本小节首先简单介绍了如何在.NET通过调用Win32 API来模拟键盘的操作,进而通过实例演示了模拟鼠标与模拟键盘在基于UI Automation的自动化测试中应用。

  • 相关阅读:
    RavenScheme简介
    我终于理解了LISP『代码即数据|数据即代码』的含义
    汉编随想(一)
    SICP的一些练习题
    linux下Script小计
    vscode小计
    软硬连接区别
    find过滤大小执行操作
    pyqt5和qt designer安装
    pyenv和virtualenv结合使用管理多python环境
  • 原文地址:https://www.cnblogs.com/kangyi/p/1596960.html
Copyright © 2020-2023  润新知