WPF 编码 UI 测试随机失败,出现奇怪的 ArgumentException

WPF coded UI test randomly fails with weird ArgumentException

我在 WPF 应用程序中编写了 UI 测试,它们偶尔会失败,但出现以下异常:

Message: Test method MyMethodNameGoesHere threw exception: System.ArgumentException: Parameter is not valid.

和 StackTrace:

at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
at Microsoft.VisualStudio.TestTools.UITesting.LoggerUtility.GetDesktopImage()
at Microsoft.VisualStudio.TestTools.UITesting.LoggerUtility.CaptureScreenShotAndDrawBounds(Int32 x, Int32 y, Int32 width, Int32 height, Int32 borderWidth, Boolean isActualControlBounds)
at Microsoft.VisualStudio.TestTools.UITest.Extension.LoggerUtilities.CaptureScreenShotAndDrawBounds(Rectangle bounds, Int32 borderWidth, Boolean isActualControlBounds)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.CaptureScreenShot(UITestControl control)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.GetUITestControlString(UITestControl control)
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.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.<Find>b__175_0()
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.GetPropertyOfType[T](String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.get_Exists()
at MyProjectNamespace.UITests.TestButtonExists() in E:\...\UITests.cs:line 177

任何试图访问 UITestControl 属性的代码,如 ExistsCheckedSelected 都会抛出它。例如:

WpfButton button = UIControlBuilder<WpfButton>.Builder()
    .Parent(MainPane)
    .AutomationID(MyButtonId)
    .Build();

// ...    

Assert.IsTrue(button.Exists);

有趣的是,这个问题是随机发生的,但有一定规律。如果我 运行 一个一个地测试,那么它们工作得很好。如果我 运行 连续进行许多测试,那么一段时间后一个测试失败,然后所有后续测试也失败。我认为这可能是与内存相关的问题(泄漏或内存不足),但我确实有很多可用内存,而且进程似乎并没有消耗太多内存。

根据我的调查 UI 测试框架在 FindFirstDescendant 中捕获异常并尝试捕获屏幕截图以报告此异常,但也未能做到这一点:

// decompiled UI test framework's UITestControl.cs code
internal UITestControl FindFirstDescendant(string queryId, int maxDepth, ref int timeLeft)
{
    // ...
    try
    {
        element = this.ScreenElement.FindScreenElement(queryId, maxDepth);
    }
    catch (Exception ex) // catches exception here
    {
        // but this method does also throw exception, because of a bug:
        Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(ex, queryId); 
        throw;
    }
}

更有趣的是,这是一个非常普遍的错误,发生在 .NET Bitmap 的构造函数中(无效的宽度或高度参数?)。

由于这个 Bitmap 问题,我无法获取原始异常,所以我无法理解发生了什么。 Playback.CaptureScreenShot 标记了编译器警告抑制属性,明确规定该方法不应该抛出任何异常。
这是 UI 测试框架中的错误吗?

还有一个有趣的观察。它在我的测试目录中创建了屏幕截图,但应用程序的 window 在屏幕截图中未正确突出显示。这就是它的样子。红色是我的显示设置,蓝色是主要 window 实际所在的位置,绿色是 WPF 在测试结果屏幕截图上突出显示的方式:

角落的绿色窄线和蓝色窄线的距离相等,所以对我来说,它似乎需要应用程序的 window 在单个主显示器内的偏移量,但随后它会尝试采用通过将偏移量应用于所有显示的屏幕截图。 这可能是错误的原因(比如超出显示范围)还是只是另一回事?

因为它看起来像一个错误,所以我问过 the same question on DeveloperCommunity

好像只是不支持多屏:

Thanks for investigation on this issue. looks like you are running coded ui test with multi screen. This is actually an unsupported scenario.

Also Coded UI test is in deprecation path. Check https://docs.microsoft.com/en-us/visualstudio/test/use-ui-automation-to-test-your-code?view=vs-2017

We suggest moving to Selenium or Appium with WinAppDriver as the case may be