UI 自动化 - InvokePattern.Invoke() 阻止执行,直到集成测试中的用户交互

UI Automation - InvokePattern.Invoke() blocking execution until user interaction in integration tests

编辑:我选择了使用 FlaUI 的路线。我已经更新了这个问题的标签以包含它,并且还发布了我的解决方案作为答案。

我正在为监视某些 windows 表单应用程序的应用程序编写一些集成测试,以查看这些应用程序是否 运行 或崩溃。

其中一个要求是确定它是否显示 error window 或 information window 并采取行动因此。

例如:

为了模拟显示 信息 window 的情况,我创建了一个测试应用程序(如上所示),其中包含一个按钮,该按钮会显示一些 信息 window 点击时。

我的测试是这样的:

[Fact]
public async Task Can_Identify_An_Information_Window()
{
    //ARRANGE
    // My service that will start the app:
    await _myUIAutomationService.StartAppAsync("PathToMyTestApp");

    //Find the app window
    var appProcess = Process.GetProcessesByName("MyTestApp'sProcessName")[0];
    var appWindow = AutomationElement.FromHandle(appProcess.MainWindowHandle);

    //Find the buttons on the app window:
    var buttons = appWindow.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
    //Grab the button that will show the information window and click it to show the information window:
    foreach (AutomationElement button in buttons)
    {
        if (button.Current.Name == "Open Info Window")
        {
            // click it to open the information window:
            var invoke = (InvokePattern)button.GetCurrentPattern(InvokePattern.Pattern);
            invoke.Invoke();
        }
    }

    //ACT
    // My service that will get the status of the app including the windows it's showing:
    var appstatus = await _myUIAutomationService.GetAppStatusAsync("MyTestApp'sName");
    var informationWindow = appstatus.InformationWindows[0];

    //ASSERT
    Assert.NotNull(informationWindow);
}

我在这个测试中遇到的问题是,在显示的信息 window 上手动单击“确定”之前,我无法通过 invoke.Invoke(); 行。

我什至尝试过将事件处理程序附加到按钮来处理这个问题,但这没有成功,因为我永远无法进入那个 OnInvoked 处理程序方法:

Automation.AddAutomationEventHandler(InvokePattern.InvokedEvent,
                                        button,
                                        TreeScope.Element,
                                        OnInvoked);

// Handler for information window showing button invoke event:
private void OnInvoked(object Sender, AutomationEventArgs E)
{
    // The control never reaches here.
}

我只需要这个测试是自动的,不需要人工干预。

任何帮助/指导将不胜感激。

谢谢!

我尝试了@stuartd 在评论中建议的方式,但不幸的是,这并没有奏效,因为我 运行 遇到了同样的问题,即 .Invoke() 方法(调用直到进行人工干预)。

所以我研究了这个由 Roman Roemer 称为 FlaUI 的很棒的 nuget 包,之后一切都很顺利。

这是我的测试现在的样子:

using FlaUI.UIA3;
using FlaUI.Core.AutomationElements;

[Fact]
public async Task Can_Identify_An_Information_Window_Async()
{
    //ARRANGE
    // My service that will start the app:
    await _myUIAutomationService.StartAppAsync("PathToMyTestApp");

    //Create FLA UI core application (i.e. myApp) from the Process object (i.e. appProcess).
    var appProcess = Process.GetProcessesByName("MyTestApp'sProcessName")[0];
    var myApp = new FlaUI.Core.Application(appProcess);

    using (var automation = new UIA3Automation())
    {
        var window = myApp.GetMainWindow(automation);
        window.WaitUntilClickable(TimeSpan.FromSeconds(2)); //Wait with a timeout duration of 2 seconds.

        //Find the button
        var myBtn = window.FindFirstDescendant(cf => cf.ByText("Open Info Window"));
        myBtn.Click(true); // This will show the information window. The true flag show the mouse pointer actually finding the button and clicking it. It's very COOL!

        //ACT
        //Get the status
        var appstatus = await _myUIAutomationService.GetAppStatusAsync("MyTestApp'sName");
        var informationWindow = appstatus.InformationWindows[0];

        //ASSERT
        Assert.NotNull(informationWindow);
    }
}