您的位置:首页 > 产品设计 > UI/UE

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

2013-01-21 16:07 627 查看
Chapter 7 Simulated keyboard

7.1模拟键盘输入

7.1.1 Introduction

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

7.1.2 SendKeys Class Introduction(MSDN)

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

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

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

7.1.3 SendKeys Method(MSDN)

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 str2in
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的自动化测试中应用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐