Ожидание элемента, прежде чем щелкнуть WinAppDriver - PullRequest
0 голосов
/ 13 мая 2019

У меня такая тривиальная проблема, но я с трудом заставляю свой код правильно ждать объекта, прежде чем двигаться дальше.

У меня установлен следующий конфиг для моего драйвера

session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(60);

Я ожидал, что это будет означать, что он будет ждать минимум 60 секунд, прежде чем выдать ошибки, связанные с идентификацией элемента, такие как

Message: System.InvalidOperationException : An element could not be located on the page using the given search parameters.

Однако это не так.Я получаю ошибку около 2 секунд при попытке вызвать следующую команду.

WindowsElement btn = session.FindElementByXPath("//Button[@Name='NEXT']");
btn.Click();

Ошибка выдается в строке, где я просто определяю свойства кнопок, а не в методе Click ().Я правильно не передаю свойства элементов?Почему создание кнопки также выполняет ее поиск?

1 Ответ

1 голос
/ 14 мая 2019

Вот это открытый выпуск на github winappdriver. Взгляните на этот комментарий об этом. Кажется, это проблема с Appium. Я понятия не имею о статусе этой проблемы.

По сути, это означает, что вам придется прибегнуть к обходному пути. Использование Thread.Sleep(/*milliseconds*/) - это плохая идея .

Я реализовал цикл while в функции, чтобы получить элемент управления по идентификатору автоматизации, например:

    /// <summary>
    /// Gets a UI element based on a AutomationId.
    /// </summary>
    /// <param name="automationId">The AutomationId is a unique value that can be found with UI inspector tools.</param>
    /// <param name="controlName">The name of the UI element.</param>
    /// <param name="timeOut">TimeOut in milliseconds</param>
    /// <returns></returns>
    protected WindowsElement GetElement(string automationId, string controlName, int timeOut = 10000)
    {
        bool iterate = true;
        WindowsElement control = null;
        _elementTimeOut = TimeSpan.FromMilliseconds(timeOut);
        timer.Start();

        while (timer.Elapsed <= _elementTimeOut && iterate == true)
        {
            try
            {
                control = Driver.FindElementByAccessibilityId(automationId);
                iterate = false;
            }
            catch (WebDriverException ex)
            {
                LogSearchError(ex, automationId, controlName);
            }
        }

        timer.Stop();
        Assert.IsFalse(timer.Elapsed > _elementTimeOut, "Timeout Elapsed, element not found.");
        timer.Reset();

        return control;
    }

Использование цикла имеет некоторые преимущества по сравнению с Thread.Sleep(), оно более гибкое и у вас гораздо больше возможностей, чем просто блокирование выполнения кода.

Несколько преимуществ:

  • Ваш тестовый скрипт продолжает выполняться: представьте, что ваш скрипт останавливается на 5 секунд, пока тестируемое приложение продолжает работать. Многое может произойти за те 5 секунд, о которых ваш сценарий захочет узнать. Но это невозможно, потому что выполнение кода блокируется, если вы используете Thread.Sleep ().
  • Динамическое ожидание: цикл while будет повторяться, пока не будет выполнено условие. Это заставляет ваш сценарий продолжать тестирование, как только будет выполнено это условие, и, следовательно, ваш скрипт будет работать быстрее. Например. Вы ждете загрузки страницы. Thread.Sleep(5000) будет предполагать нормально продолжать, пока цикл знает нормально продолжить тест.
  • С помощью комбинированного таймера / тайм-аута вы можете проверить, сколько времени заняла операция (например, сохранить некоторые изменения), и, если она заняла больше времени, вы знаете, что продолжение не в порядке.

С другой стороны, этот код будет работать так же хорошо:

protected WindowsElement GetElement(string automationId, string propertyName, int timeOut = 10000)
{
    WindowsElement element = null;
    var wait = new DefaultWait<WindowsDriver<WindowsElement>>(Driver)
    {
        Timeout = TimeSpan.FromMilliseconds(timeOut),
        Message = $"Element with automationId \"{automationId}\" not found."
    };

    wait.IgnoreExceptionTypes(typeof(WebDriverException));

    try
    {
        wait.Until(Driver =>
        {
            element = Driver.FindElementByAccessibilityId(automationId);

            return element != null;
        });
    }
    catch(WebDriverTimeoutException ex)
    {
        LogSearchError(ex, automationId, propertyName);
        Assert.Fail(ex.Message);
    }

    return element;
}

Выше кода будет выбрасывать WebDriverTimeoutException вместо непрерывного выброса NoSuchElementException. Он не использует цикл while, но я подозреваю, что wait.Until(...) делает нечто подобное, поскольку WinAppDriver опрашивает графический интерфейс каждые 500 мс (см. Свойство PollingInterval объекта DefaultWait.

...