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问题.
aku*_*aku 11
@Matt David,
请阅读文档并查看Microsoft CompositeWPF(aka Prism)的代码示例.这是一个专门用于教授如何以测试驱动方式处理MVP/MVC架构的项目.他们的示例应用程序包含演示者\控制器的单元测试和UI的非常酷的验收测试(他们使用White框架来模拟用户操作)
Gis*_*shu 11
手动.我不是自动化UI测试的忠实粉丝,如果这就是你所得到的.我不确定WPF的指导(需要通过aku的链接阅读)..因为它们仍然可以说是固执...... WPF从"正确的方式"的角度来看还没有稳定下来.除非你使用这些不断发展的框架之一.我会保守的
PS:你可能想要观看这个(Mary Poppendieck的Google精益谈话)..尤其是关于在测试中自动化的部分
2016更新:使用免费的TestStack.White框架自动执行WPF UI测试
将启动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();
}
这个问题仍然相关,但许多答案已经过时了。@deadpikle在评论 中提出了一个非常好的解决方案,我尝试了它,我想将其作为答案,以便更多的人看到它。
所以,这是一个库https://github.com/FlaUI/FlaUI。以下是 WPF 应用程序的快速入门指南:
从 nuget 安装 FlaUI.UIA3
编写此代码来测试应用程序是否正确运行(但插入您的字符串文字):
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();
        }
    }
}
此代码在 GitHub Actions 管道中也运行良好。
由于编码 UI 框架在 Visual Studio 2019 版(已弃用编码 UI)之后过期,因此微软建议使用带有 WinAppDriver 的 Appium 来测试 Windows 应用程序(桌面和 UWP)。您可以直接使用 Appium(带有 WinAppDriver)或 WinAppDriver 来运行测试(带有或不带有 Appium 的 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);
        }
    } 
        [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();
            }
        }
(示例代码主要复制自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
在这里你会找到正确的版本和下载路径:
const WAD_VER = "1.1";
const WAD_DL = `https://github.com/Microsoft/WinAppDriver/releases/download/v${WAD_VER}/WindowsApplicationDriver.msi`;
如果您安装了正确的 WinAppDriver,您就可以启动 Appium。
重要提示:您必须更改 ApplicationDriverUrl
protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723/wd/hub";
工具:
WindowsAppDriver 和 UI REcorder 发布 或下载WinAppDriver 存储库并在子目录 tools\UIRecorder 中构建 WinAppDriverUIRecorder.sln
其他链接: WinAppDriver 常见问题 Appium
| 归档时间: | 
 | 
| 查看次数: | 45561 次 | 
| 最近记录: |