Appium 桌面应用程序测试抛出元素无法定位异常,但在测试运行之前启动应用程序时通过

Appium desktop app test throws element could not be located exception, but passes when the app is launched before the test runs

我正在尝试学习 Appium 并将其用于 WPF 应用程序测试。针对计算器或记事本的测试 运行 没问题,但最近我在尝试测试自定义 WPF 应用程序时遇到了问题。

Appium 桌面应用程序测试抛出 "An element could not be located on the page using the given search parameters" 异常,但在测试 运行 之前启动应用程序时可以顺利通过。所以我想我的 Setup/Init 阶段有点不正确,但我不知道为什么。

当测试 运行 时没有先启动应用程序(因此当设置阶段必须启动应用程序时)时会发生错误。 当应用程序在测试 运行 之前启动时测试通过,甚至当它在之前失败的测试 运行.

中保持打开状态时

应用程序启动大约需要 10 到 15 秒,在此期间首先出现斜线屏幕,然后是应用程序的主 window。

Appium.WebDriver项目中使用了nuget packege,版本3.0.0.2

我已经尝试 Thread.Sleep 30 秒,但没有解决问题。

[TestFixture]
public class DesktopAppSession
{
    protected WindowsDriver<WindowsElement> _session;
    protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
    protected const string AppId = @"<path to app.exe>";

    [SetUp]
    public void TestInit()
    {
        if (_session != null)
            return;

        var appCapabilities = new DesiredCapabilities();
        appCapabilities.SetCapability("app", AppId);
        appCapabilities.SetCapability("deviceName", "WindowsPC");
        _session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);

        Assert.IsNotNull(_session);

        Thread.Sleep(TimeSpan.FromSeconds(30));

        _session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
    }

    [TearDown]
    public void TestCleanup()
    {
        if (_session != null)
        {
            _session.Quit();
            _session = null;
        }
    }

    [Test]
    public void UserInfoModalShowsUp()
    {
        var userInfoButtonAName = "UserInfoButtonAName";
        var userInfoButtonId = "UserInfoButtonAID";

        var userInfoButton = _session.FindElementByAccessibilityId(userInfoButtonId);

        Assert.True(userInfoButton != null);

        userInfoButton.Click();

        var userDetailsTitleLabel = _session.FindElementByName("User details");

        userDetailsTitleLabel?.Click();

        Assert.True(true);
    }
}

异常信息:

System.InvalidOperationException HResult=0x80131509 Message=使用给定的搜索参数无法在页面上找到元素。 源=WebDriver 堆栈跟踪: 在 OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(响应错误响应) 在 OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary2 parameters) at OpenQA.Selenium.Remote.RemoteWebDriver.FindElement(String mechanism, String value) at OpenQA.Selenium.Appium.AppiumDriver1.FindElement(String by, String value)

来自 WinAppDriver 的日志:

"POST /session/23293B57-F396-47CC-83EF-FCA491E269B0/element HTTP/1.1 接受:application/json、image/png 内容长度:56 内容类型:application/json;charset=utf-8 主机:127.0.0.1:4723

{"using":"accessibility id","value":"UserInfoButtonAID"} HTTP/1.1 404 未找到 内容长度:139 内容类型:application/json

{"status":7,"value":{"error":"no such element","message":"An element could not be located on the page using the given search parameters."}}"

您很可能需要将 window 句柄切换到正确的句柄。

Winappdriver 使用 window 顶级句柄 windows。最有可能的是,您的启动画面将是顶级 window,而您的实际应用程序也将是顶级 window。 所以 winappdriver 将至少有 2 window 个句柄。您的驱动程序(在您的情况下为 _session)有一个名为 WindowHandles 的 属性,其中包含一个 window 句柄列表。这些句柄按时间顺序添加,因此最近的句柄(来自您的应用程序的句柄)应该是最后一个 window 句柄。

此示例向您展示如何切换 window 句柄:

if (_session.CurrentWindowHandle != _session.WindowHandles.Last())
{
    _session.SwitchTo().Window(_session.WindowHandles.Last());
}

您还可以通过检查驱动程序的页面源 属性 来验证您是否具有正确的 window 句柄,如下所示:_session.PageSource;。页面源是当前选定 window 句柄的 xml 表示。您可以将它放在 Visual Studio 手表中,然后将 xml 复制到 xml 格式化实用程序中以提高可读性。

有关启动画面问题和解决该问题的替代方法的更多信息,请参见 here。 请务必查看用户 timotiusmargo 的回答。