【问题标题】:Appium desktop app test throws element could not be located exception, but passes when the app is launched before the test runsAppium桌面应用程序测试抛出元素无法定位异常,但在测试运行之前启动应用程序时通过
【发布时间】:2019-05-29 15:12:01
【问题描述】:

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

Appium 桌面应用程序测试抛出“使用给定的搜索参数无法在页面上定位元素”异常,但在测试运行之前启动应用程序时可以顺利通过。所以我猜我的设置/初始化阶段是不正确的,但我不知道为什么。

在未先启动应用程序的情况下运行测试时会发生错误(因此当设置阶段必须启动应用程序时)。 如果应用在测试运行之前启动,或者即使在之前失败的测试运行中保持打开状态,测试也会通过。

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

项目中使用了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 H结果=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/元素 HTTP/1.1 接受:application/json, image/png 内容长度:56 内容类型:application/json;charset=utf-8 主机:127.0.0.1:4723

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

{"status":7,"value":{"error":"no such element","message":"使用给定的搜索参数无法在页面上找到一个元素。"}}"

【问题讨论】:

    标签: c# appium-desktop winappdriver


    【解决方案1】:

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

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

    这个例子告诉你如何切换窗口句柄:

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

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

    有关启动画面问题的其他信息和解决它的替代方法,可以找到here。 请务必查看用户 timotiusmargo 的答案。

    【讨论】:

    • 原来如此!谢谢 :) CurrentWindowHandle 和 WindowHandles 中的句柄具有不同的值。我之前检查过 WindowHandles,但一次只有一个句柄,所以我认为它必须与当前的句柄相同,并且没有真正检查值。下次我会尝试更彻底。再次感谢您:)
    猜你喜欢
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多