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

使用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我接触的比较少,实在抱歉,但我会尽自己最大的努力,还望多多帮忙啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: