如何测试WPF用户界面?

Mat*_*vid 57 .net testing wpf

使用带有MVC/MVP架构的win表单,我通常会使用一个类来包装视图以测试UI,同时使用模拟和控制器/演示者的模拟.包装器类将使UI中的大多数内容成为测试运行器通过属性和事件的可观察属性.

这是测试WPF应用程序的可行方法吗?有没有更好的办法?有什么值得注意的吗?

Kje*_*sen 57

至于测试本身,您可能最好使用UI自动化框架.或者如果你想要一个更流畅和wpf/winforms/win32/swt独立的方式使用框架,你可以从Codeplex 下载White(前提是你可以在你的环境中使用开源代码).

对于陷阱; 如果您正在尝试测试您的视图,您可能会遇到一些线程问题.例如,如果您正在运行NUnit,默认的testrunner将在MTA(多线程公寓)中运行,而WPF需要作为STA(单线程公寓)运行.Mike Two对单元测试WPF有一个非常简单的入门,但没有考虑线程问题.Josh Smith对这篇帖子中的线程问题有一些想法,他也指出Chris Hedgate的这篇文章.Chris使用Peter Provost的CrossThreadTestRunner的修改版本以更加友好的方式包装MTA/STA问题.

  • 此答案中的 UI 自动化链接已过时。这是更新的链接:https://learn.microsoft.com/en-us/windows/win32/winauto/entry-uiauto-win32 (2认同)

aku*_*aku 11

@Matt David,

请阅读文档并查看Microsoft CompositeWPF(aka Prism)的代码示例.这是一个专门用于教授如何以测试驱动方式处理MVP/MVC架构的项目.他们的示例应用程序包含演示者\控制器的单元测试和UI的非常酷的验收测试(他们使用White框架来模拟用户操作)


Gis*_*shu 11

手动.我不是自动化UI测试的忠实粉丝,如果这就是你所得到的.我不确定WPF的指导(需要通过aku的链接阅读)..因为它们仍然可以说是固执...... WPF从"正确的方式"的角度来看还没有稳定下来.除非你使用这些不断发展的框架之一.我会保守的

  • 无情地测试(自动优选TDDed)逻辑/演示者/控制器.我不是在提倡邋iness或嗜睡.
  • 保持UI皮肤薄,并让一些讨厌的测试人员通过探索性测试得到(手动)破解 - 当涉及UI时,没有什么能像'来自地狱的测试者'一样好.努力:自动化这种测试的增益比是巨大的,没有抓住一切,没有意义......除了安抚高层'看看经理!没有手!自我测试用户界面!'

PS:你可能想要观看这个(Mary Poppendieck的Google精益谈话)..尤其是关于在测试中自动化的部分

  • 你忘记了回归测试 - 手动测试人员通过数百种表格来检查一些可以更容易自动完成的基本内容真是太痛苦了.更好地为测试人员节省了这些繁琐的东西,所以他可以集中精力进行讨厌的测试. (8认同)
  • 手动测试不能完全取代自动(反之亦然).自动化测试的目的不是为了发现错误,而是为了确保新的更改不会破坏已经过测试的旧功能. (5认同)

Jus*_*tas 9

2016更新:使用免费的TestStack.White框架自动执行WPF UI测试

  • Project White已被放弃,但其后继者TestStack.White可通过NuGet包获得.
  • TestStack.White具有启动WPF应用程序,查找窗口/ 用户控件元素,单击按钮/元素,模拟鼠标和键盘事件,等待等的实用程序方法.
  • 将启动WPF应用程序,单击按钮并检查结果的示例如下所示:

    using TestStack.White;
    using TestStack.White.UIItems;
    using TestStack.White.Factory;
    
    [TestMethod]
    public void TestDoSomething()
    {
        //Opens the app
        var app = Application.Launch("MyApp.exe");
    
        //Finds the main window (this and above line should be in [TestInitialize])
        var window = app.GetWindow("My App Window Title", InitializeOption.NoCache);
    
        //Finds the button (see other Get...() methods for options)
        var btnMyButton = window.Get<Button>("btnMyButtonWPFname");
    
        //Simulate clicking
        btnMyButton.Click();
    
        //Gets the result text box 
        //Note: TextBox/Button is in TestStack.White.UIItems namespace
        var txtMyTextBox = window.Get<TextBox>("txtMyTextBox");
    
        //Check for the result
        Assert.IsTrue(txtMyTextBox.Text == "my expected result");
    
        //Close the main window and the app (preferably in [TestCleanup])
        app.Close();
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 2020 年你好——“TestStack/White”确实已被弃用,但它现在有一个名为“FlaUI”的后继者,您可以在此处获取:https://github.com/FlaUI/FlaUI (4认同)

Lev*_*Lev 7

这个问题仍然相关,但许多答案已经过时了。@deadpikle在评论 中提出了一个非常好的解决方案,我尝试了它,我想将其作为答案,以便更多的人看到它。

所以,这是一个库https://github.com/FlaUI/FlaUI。以下是 WPF 应用程序的快速入门指南:

  1. 从 nuget 安装 FlaUI.UIA3

  2. 编写此代码来测试应用程序是否正确运行(但插入您的字符串文字):

    using FlaUI.Core;
    using FlaUI.Core.AutomationElements;
    using FlaUI.UIA3;
    using FluentAssertions;
    using System;
    using Xunit;
    
    namespace Functional
    {
        public sealed class General : IDisposable
        {
            private readonly Application _app = Application.Launch(@"..\App.exe");
    
            [Fact]
            public void AppStarts()
            {
                using var automation = new UIA3Automation();
                Window window = _app.GetMainWindow(automation, TimeSpan.FromSeconds(3));
    
                window.Should().NotBeNull("null means the window failed to load");
    
                window.Title.Should().Be("App title",
                    "otherwise, it could be message box with error in case of the wrong configuration");
            }
    
            public void Dispose()
            {
                _app.Close();
                _app.Dispose();
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

此代码在 GitHub Actions 管道中也运行良好。


HHe*_*enn 6

由于编码 UI 框架在 Visual Studio 2019 版(已弃用编码 UI)之后过期,因此微软建议使用带有 WinAppDriver 的 Appium 来测试 Windows 应用程序(桌面和 UWP)。您可以直接使用 Appium(带有 WinAppDriver)或 WinAppDriver 来运行测试(带有或不带有 Appium 的 WinAppDriver)。

直接WinAppDriver

以下是直接使用 WinAppDriver 的简短说明:

  • 下载并安装 WinAppDriver:

    WinAppDriver 发布

  • 在 Windows 设置中启用开发者模式

  • 启动 WinAppDriver:

    C:\Program Files (x86)\Windows 应用程序驱动程序\WinAppDriver.exe

  • 创建一个新的 Visual Studio 2019 单元测试项目 (.NET Framework)

  • 添加 NuGet 包:Appium.WebDriver Microsoft.WinAppDriver.Appium.WebDriver(来自微软的评论:建议使用 WinAppDriver NuGet 包以充分利用 Actions API 的高级输入。)

  • 添加一个新类 DesktopSession:

    public class DesktopSession
    {
        protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
        private const string NotepadAppId = @"C:\Windows\System32\notepad.exe";
    
        protected static WindowsDriver<WindowsElement> session;
        protected static WindowsElement editBox;
    
        public static void Setup(TestContext context)
        {
            // Launch a new instance of Notepad application
            if (session == null)
            {
                // Create a new session to launch Notepad application
                var appCapabilities = new DesiredCapabilities();
                appCapabilities.SetCapability("app", NotepadAppId);
                appCapabilities.SetCapability("platformName", "Windows");
                appCapabilities.SetCapability("deviceName ", "WindowsPC");
                session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
                Assert.IsNotNull(session);
                Assert.IsNotNull(session.SessionId);
    
                // Set implicit timeout to 1.5 seconds to make element search to retry every 500 ms for at most three times
                session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1.5);
    
                // Keep track of the edit box to be used throughout the session
                editBox = session.FindElementByClassName("Edit");
                Assert.IsNotNull(editBox);
            }
        }
    
        public static void TearDown()
        {
            // Close the application and delete the session
            if (session != null)
            {
                session.Close();
    
                try
                {
                    // Dismiss Save dialog if it is blocking the exit
                    session.FindElementByName("Nicht speichern").Click();
                }
                catch { }
    
                session.Quit();
                session = null;
            }
        }
    
        [TestInitialize]
        public void TestInitialize()
        {
            // Select all text and delete to clear the edit box
            editBox.SendKeys(Keys.Control + "a" + Keys.Control);
            editBox.SendKeys(Keys.Delete);
            Assert.AreEqual(string.Empty, editBox.Text);
        }
    } 
Run Code Online (Sandbox Code Playgroud)
  • 更改 UnitTest1 类中的代码
        [TestClass]
        public class UnitTest1 : DesktopSession
        {
            [TestMethod]
            public void EditorEnterText()
            {
                Thread.Sleep(TimeSpan.FromSeconds(2));
                editBox.SendKeys("abcdeABCDE 12345");
                Assert.AreEqual(@"abcdeABCDE 12345", editBox.Text);
            }
    
            [ClassInitialize]
            public static void ClassInitialize(TestContext context)
            {
                Setup(context);
            }
    
            [ClassCleanup]
            public static void ClassCleanup()
            {
                TearDown();
            }
        }
Run Code Online (Sandbox Code Playgroud)
  • 运行你的测试

(示例代码主要复制自WinAppDriver .NotepadTest)。

带有 WinAppDriver 的 Appium

如果你想使用 Appium 运行你的测试,那么你必须在你的机器上安装了正确版本的 WinAppDriver。Appium 的安装程序还应该在您的机器上安装正确版本的 WinAppDriver(请为所有用户安装 Appium)。不幸的是,就我而言,这不起作用。所以我看了一下文件:

C:\Program Files\Appium\resources\app\node_modules\appium\node_modules\appium-windows-driver\lib\installer.js
Run Code Online (Sandbox Code Playgroud)

在这里你会找到正确的版本和下载路径:

const WAD_VER = "1.1";
const WAD_DL = `https://github.com/Microsoft/WinAppDriver/releases/download/v${WAD_VER}/WindowsApplicationDriver.msi`;
Run Code Online (Sandbox Code Playgroud)

如果您安装了正确的 WinAppDriver,您就可以启动 Appium。

重要提示:您必须更改 ApplicationDriverUrl

protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723/wd/hub";
Run Code Online (Sandbox Code Playgroud)

工具:

WindowsAppDriver 和 UI REcorder 发布 或下载WinAppDriver 存储库并在子目录 tools\UIRecorder 中构建 WinAppDriverUIRecorder.sln

介绍 WinAppDriver UI 记录器

  • inspect.exe:需要 Windows SDK(在 C:\Program Files (x86)\Windows Kits\10\bin 中查找)

其他链接: WinAppDriver 常见问题 Appium