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);
}
}
编辑:我选择了使用 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);
}
}