之前花了数周的时间搭了个基于UI Automation的自动化框架。期间发现一个问题,当被测试程序中的element非常多的时候,恰巧要寻找的element位于tree的末端的话,可能性能会比较的低(不知道微软对FindFirst方法有没有做性能上的优化)。于是乎想寻找有没有效率比较高的方法,在MSDN中查询了一下,发现提供了Cache的功能(链接)。后来才发现高效的原理是在进行FindFirst之时将element相应的property合pattern进行cache处理,以后再对element的property和patter进行查询的时候会比较高效,而且还特别强调了对与服务器相连的WPF程序特别有效。虽然和我本意有点出入,但是也算个提高效率的技能,研究一下先:
编写了个两个函数,一个采用了cache,另一个没有,功能都是寻找被测试程序上的一个element,然后再得到其property(选择得到其property的结果也类似),来看看其效率到底差多少。为了使其结果更加明显,故采用了循环来进行高次数访问下的效率区别。
class Program
{
static void Main(string[] args)
{
AutomationElement aeDesktop = AutomationElement.RootElement;
AutomationElement appElement = aeDesktop.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.AutomationIdProperty, "_RVMainWindow"));
SearchElememtWithoutCache(appElement);
SearchElementWithCache(appElement);
Console.ReadLine();
}
static void SearchElememtWithoutCache(AutomationElement appElement)
{
Stopwatch stopwatch = new Stopwatch();
AutomationElement aeName =
appElement.FindFirst(TreeScope.Subtree,
new PropertyCondition(AutomationElement.AutomationIdProperty, "name"));
stopwatch.Start();
string nameID="";
for (int i = 0; i < 10; i++)
{
nameID = aeName.Current.AutomationId;
}
stopwatch.Stop();
Console.WriteLine("Without cache used milliseconds: " + stopwatch.ElapsedMilliseconds);
}
static void SearchElementWithCache(AutomationElement appElement)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
CacheRequest cacheRequest = new CacheRequest();
cacheRequest.AutomationElementMode = AutomationElementMode.None;
cacheRequest.TreeFilter = Automation.ControlViewCondition;
cacheRequest.Add(AutomationElement.AutomationIdProperty);
AutomationElement aeName = null;
using (cacheRequest.Activate())
{
aeName =
appElement.FindFirst(TreeScope.Subtree,
new PropertyCondition(AutomationElement.AutomationIdProperty, "name"));
}
stopwatch.Start();
string nameId="";
for (int i = 0; i < 10; i++)
{
nameId = aeName.Cached.AutomationId;
}
stopwatch.Stop();
Console.WriteLine("With cache used milliseconds: " + stopwatch.ElapsedMilliseconds);
}
}
运行结果如下:
· 进行10次循环:
Without cache used milliseconds: 2
With cache used milliseconds: 310
· 进行100次循环:
Without cache used milliseconds: 23
With cache used milliseconds: 312
· 进行1000次循环:
Without cache used milliseconds: 252
With cache used milliseconds: 305
· 进行10000次循环:
Without cache used milliseconds: 2430
With cache used milliseconds: 315
结果令我大吃一惊,在elememt被的属性被访问1000次之前,其效率都是差于普通方式访问的,当访问次数达到10000次的时候,其效率的提高的是比较明显的,难道说如果被测试程序element操作次数少于1000次的话,不建议采用cache?不知道事实的真相是不是如此!