使用UI Automation实现自动化测试 (InvokePattern)
2015-12-05 13:17
411 查看
InvokePattern
InvokePattern是UIA中最常用的Pattern之一,WPF和Winform中的button控件都支持InvokePattern。对InvokePattern的Invoke()方法的调用应立即返回,没有出现阻止情况。但是,此行为完全依赖于 Microsoft UI 自动化提供程序实现。在调用 Invoke()会引起阻止问题(如Winform中的模式对话框,但是WPF中的对话框的处理方式和winform不同,所以可以使用Invoke()方法来操作WPF中的模式对话框,因为WPF中的模式对话框不会出现阻止的问题)的情况下,要调用此方法,则需要另起线程来操作。
using System;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;
namespace UIATest
{
class Program
{
static void Main(string[] args)
{
Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
int processId = process.Id;
AutomationElement element = FindElementById(processId, "button1");
InvokePattern currentPattern = GetInvokePattern(element);
currentPattern.Invoke();
}
/// <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;
}
#region InvokePattern helper
/// <summary>
/// Get InvokePattern
/// </summary>
/// <param name="element">AutomationElement instance</param>
/// <returns>InvokePattern instance</returns>
public static InvokePattern GetInvokePattern(AutomationElement element)
{
object currentPattern;
if (!element.TryGetCurrentPattern(InvokePattern.Pattern, out currentPattern))
{
throw new Exception(string.Format("Element with AutomationId '{0}' and Name '{1}' does not support the InvokePattern.",
element.Current.AutomationId, element.Current.Name));
}
return currentPattern as InvokePattern;
}
#endregion
}
}
被测程序xaml代码如下:
<Window x:Class="WpfApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="219" Width="353">
<Grid>
<Button Height="23" HorizontalAlignment="Left" Click="button1_Click" Margin="50,0,0,62" Name="button1" VerticalAlignment="Bottom" Width="75">Button</Button>
</Grid>
</Window>
对应的cs文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Use InvokePattern invoke button.");
}
}
}
本文主要针对InvokePattern的Invoke方法来操作button控件。
关于您提到的
在调用 Invoke() 会引起阻止问题
原因是UIAutomation对于WPF的实现是native的, 通信是通过named pipe
对于WinForm等Win32的实现是DCOM Message, 也就是Windows Message, 所以需要message pump
不过无论如何, 把test client中的main thread标记为STAThread, 都因该没有问题
希望作者能多介绍下UI Automation中更多的知识, 比如UI Event怎么用,还有常见的问题, 比如timming issue等
在调用
Invoke() 会引起阻止问题
此问题困扰我很久,谢谢解答,对于UI Automation中的UI Event我接触的比较少,实在抱歉,但我会尽自己最大的努力,还望多多帮忙啊
相关文章推荐
- (译)如何自定义UIDocument的子类
- DDuilib入门【一】
- Ubuntu 15.10下android studio 1.5,新建android项目,gradle build running永不停止
- UIScrollView基本用法
- 第25篇 jQuer快速学习(上)---选择器和DOM操作
- 爬爬爬之路:UI(十五) KVO
- Code Forces 592 B. The Monster and the Squirrel(水~)
- android Bluetooth开发基本流程
- poj 1679 The Unique MST(次小生成树变形)
- ios_Cocoa框架 “Foundation”和“UIKit”的区别
- android Bluetooth的实现蓝牙操作
- UIView(包括子类)的几个初始化时执行动作的时机
- Leetcode Longest Increasing Subsequence
- Code Forces 591 A. Wizards' Duel(水~)
- OC-7.NSSet NSValue NSNumber
- block bio queue request等
- 45.KVO(Key-Value-Observer)键值观察者
- UIPageControl控件的常用属性
- 黑马程序员-Java中只读类String和StringBuffer、StringBuilder类)
- HDU-5538-House Building【2015长春赛区】