录制的 CodedUI 找不到录制的控件

Recorded CodedUI can't find recorded Controls

所以我已经使用 Visual Studio 中的代码生成器来生成编码的 UI 测试。我们有一个带有 TreeList 的 wpf 应用程序。我将它记录到第一个框,输入一个值,然后单击第二个框,然后输入一个新值。没什么特别的。

public void RecordedMethod1()
{
    #region Variable Declarations
    WpfCell uIItemCell = this.UIWindowWindow.UIEntityTesterControlCustom.UIEntityTesterTreeListTree.UIEntityTesterTreeListTreeItem.UIItemCell;
    WpfEdit uIInvoice1InvoiceIDEdiEdit = this.UIWindowWindow.UIEntityTesterControlCustom.UIEntityTesterTreeListTree.UIEntityTesterTreeListTreeItem.UIItemCell.UIInvoice1InvoiceIDEdiEdit;
    WpfCell uIItemCell1 = this.UIWindowWindow.UIEntityTesterControlCustom.UIEntityTesterTreeListTree.UIEntityTesterTreeListTreeItem.UIItemCell1;
    WpfEdit uI_localTextBoxEdit = this.UIWindowWindow.UIEntityTesterControlCustom.UIEntityTesterTreeListTree.UIEntityTesterTreeListTreeItem.UIItemCell11.UI_localTextBoxEdit;
    #endregion

    // Click cell
    Mouse.Click(uIItemCell, new Point(92, 18));

    // Type '1' in 'Invoice:1/InvoiceID|Editor' text box
    uIInvoice1InvoiceIDEdiEdit.Text = this.RecordedMethod1Params.UIInvoice1InvoiceIDEdiEditText;

    // Click cell
    Mouse.Click(uIItemCell1, new Point(136, 9));

    // Type '2/1/2012' in '_localTextBox' text box
    uI_localTextBoxEdit.Text = this.RecordedMethod1Params.UI_localTextBoxEditText;
}

#region Properties
public virtual RecordedMethod1Params RecordedMethod1Params
{
    get
    {
        if ((this.mRecordedMethod1Params == null))
        {
            this.mRecordedMethod1Params = new RecordedMethod1Params();
        }
        return this.mRecordedMethod1Params;
    }
}

它在第一次 Mouse.Click() 调用时因这个错误而崩溃

Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotFoundException was unhandled by user code
HResult=-268111872
Message=The playback failed to find the control with the given search properties. Additional Details: 
TechnologyName:  'UIA'
FrameworkId:  'Wpf'
ControlType:  'Custom'
ClassName:  'Uia.EntityTesterControl'
AutomationId:  'EntityTesterControl'
Search may have failed at 'Test Suite Tools' Custom as it may have virtualized children. If the control being searched is descendant of 'Test Suite Tools' Custom then including it as the parent container may solve the problem.
Source=Microsoft.VisualStudio.TestTools.UITesting
BasicMessage=The playback failed to find the control with the given search properties.
RootElement=""
StackTrace:
at Microsoft.VisualStudio.TestTools.UITesting.Playback.MapControlNotFoundException(COMException ex, IPlaybackContext context)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowComException(COMException innerException, IPlaybackContext context)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(Exception exception, IPlaybackContext context)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(Exception exception, String queryId)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
at Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetUITestControlRecursive(Boolean useCache, Boolean alwaysSearch, ISearchArgument searchArg, IList`1 windowTitles, Int32& timeLeft)
at Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetUITestControlRecursive(Boolean useCache, Boolean alwaysSearch, ISearchArgument searchArg, IList`1 windowTitles, Int32& timeLeft)
at Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetUITestControlRecursive(Boolean useCache, Boolean alwaysSearch, ISearchArgument searchArg, IList`1 windowTitles, Int32& timeLeft)
at Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetUITestControlRecursive(Boolean useCache, Boolean alwaysSearch, ISearchArgument searchArg, IList`1 windowTitles, Int32& timeLeft)
at Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetElement(Boolean useCache, ISearchArgument searchArg)
at Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.Search(ISearchArgument searchArg)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindInternal()
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindPrivate()
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.<Find>b__37()
at Microsoft.VisualStudio.TestTools.UITesting.CodedUITestMethodInvoker.InvokeMethod[T](Func`1 function, UITestControl control, Boolean firePlaybackErrorEvent, Boolean logAsAction)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.Find()
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.GetPropertyPrivate(String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.<>c__DisplayClass3b.<GetProperty>b__3a()
at Microsoft.VisualStudio.TestTools.UITesting.CodedUITestMethodInvoker.InvokeMethod[T](Func`1 function, UITestControl control, Boolean firePlaybackErrorEvent, Boolean logAsAction)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.GetProperty(String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.ALUtility.GetTechElementFromUITestControl(UITestControl uiTestControl)
at Microsoft.VisualStudio.TestTools.UITesting.ActionExecutorManager.GetActionExecutor(UITestControl uiControl)
at Microsoft.VisualStudio.TestTools.UITesting.Mouse.ClickImplementation(UITestControl control, MouseButtons button, ModifierKeys modifierKeys, Point relativeCoordinate)
at Microsoft.VisualStudio.TestTools.UITesting.Mouse.<>c__DisplayClass6.<Click>b__5()
at Microsoft.VisualStudio.TestTools.UITesting.CodedUITestMethodInvoker.InvokeMethod[T](Func`1 function, UITestControl control, Boolean firePlaybackErrorEvent, Boolean logAsAction)
at Microsoft.VisualStudio.TestTools.UITesting.Mouse.Click(UITestControl control, MouseButtons button, ModifierKeys modifierKeys, Point relativeCoordinate)
at Microsoft.VisualStudio.TestTools.UITesting.Mouse.Click(UITestControl control, Point relativeCoordinate)
at RoadExercises.UIMap.RecordedMethod1() in c:\Users\dtan\Documents\Visual Studio 2013\Projects\CodedUITestProject1\CodedUITestProject1\UIMap.Designer.cs:line 46
at RoadExercises.RoadExercises.IrVerifyFillInField(String p1, String p2) in c:\Users\dtan\Documents\Visual Studio 2013\Projects\CodedUITestProject1\CodedUITestProject1\RoadExercises.cs:line 169
at RoadExercises.RoadExercises.RoadExercise1b() in c:\Users\dtan\Documents\Visual Studio 2013\Projects\CodedUITestProject1\CodedUITestProject1\RoadExercises.cs:line 139
InnerException: System.Runtime.InteropServices.COMException
HResult=-2147467259
Message=Error HRESULT E_FAIL has been returned from a call to a COM component.
Source=Microsoft.VisualStudio.TestTools.UITest.Playback
ErrorCode=-2147467259
StackTrace:
at Microsoft.VisualStudio.TestTools.UITest.Playback.Engine.IScreenElement.FindAllDescendants(String bstrQueryId, Object& pvarResKeys, Int32 cResKeys, Int32 nMaxDepth)
at Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindAllScreenElement(String queryId, Int32 depth, Boolean singleQueryId, Boolean throwException, Boolean resetSkipStep)
at Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindScreenElement(String queryId, Int32 depth, Boolean resetSkipStep)
at Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindScreenElement(String queryId, Int32 depth)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
InnerException: 

据我所知(当我进行各种缓慢的 steps/null 检查时)。找不到 UIEntityTesterTreeListTree 的控件。看起来它不在映射的路径下。显然,这条路径不是 UIWindowWindow.UIEntityTesterControlCustom.UIEntityTesterTree 的简单情况,而是在此之前它必须经过几个子区域。

我尝试重新映射它几次,但没有成功。我不想硬编码,所以希望这里有人可以帮我找到 issue/way 来解决这个问题。

谢谢!

您必须编辑 WpfCell 的搜索属性以确保它们使用正确的值。 Coded UI Test Builder 通常过于具体,无法始终正常工作,而且我发现将值编辑到最小公分母是最佳做法。 Here's 一个很好的起点。

我没有太多修改搜索属性以按位置在树中查找位置的经验,因为我发现这会使代码更加复杂,而且根据我的经验,它并不总是非常稳定。如果在开发过程中添加或移动了某些元素,它将破坏您的所有代码,您将不得不返回并更改所有映射的参数。我的建议是让开发人员向元素添加一个标识 属性(例如,唯一的名称标签),以便您可以在搜索中指定它。

如果您熟悉 C#,则编写映射代码可能会更容易。当然,如果你有一个特定的 属性 元素,那会更容易。例如:

<wpfelement>
    <subElement name='someElement'>
        <button name='oneButton'>Click me.</button>
    </subElement>
</wpfelement>
<wpfelement>
    <subElement name='someOtherElement'>
        <button name='secondButton'>Click me.</button>
    </subElement>
</wpfelement>

将通过以下方式在您的地图中找到:

public WpfButton UIItemCell
{
    get
    {
        WfpButton target = new WpfButton(parentElement);
        target.SearchProperties["name"] = "secondButton";
        return target;
    }
}

这样,无论元素在树中的什么位置,Coded UI 引擎都能轻松找到它。如果您想要的单元格没有任何标识属性,将它们添加到 UI 会很有帮助,但您也可以使用 element.GetChildren() 和过滤从最近的具有标识符的父级导航从那里开始。