2015-03-09 2 views
-3

Я все еще новичок в тестировании с Watir, но я читал повсюду около waiting with Watir, и я не могу найти решение моей проблемы.Watir wait_until_present times out вместо того, чтобы возвращать false

В основном я хочу wait_while_present и wait_until_present работать, когда страница загружается. Когда я понял, что оба тайм-аута, я попытался написать свою собственную janky версию, используя element.present?, но это тоже не так. Я думаю, что это может быть проблемой с текущей версией watir-webdriver.

Вот пример теста, который дает мне много неприятностей:

def test_rows_per_page() 
    begin 
    browser.element(:id => 'moar-rows').when_present.click 
    browser.element(:id => 'loading').wait_while_present 
    assert_text = browser.element(:id => 'num-rows').text 

    browser.element(:id => 'less-rows').when_present.click 
    browser.element(:id => 'loading').wait_while_present 
    diff_text = browser.element(:id => 'num-rows').text 

    if !(assert_text.eql? diff_text) 
     screen_capture() 
     assert_passed() 
    else 
     screen_capture() 
     assert_failed() 
    end 
    rescue 
    screen_capture() 
    increment_failed() #this is how I know it's timing out 
    end 
end 

Я попытался тестирования puts load_element.present?(timeout=1), и он просто не может быстрее. Таким образом, wait_until_present не возвращает false, когда элемент отсутствует. Как мне вернуть false?

Я мог бы попробовать это, что в ответ на вопрос, который я связан с в самом начале, но я не уверен, если он решает мою проблему:

Timeout::timeout(input_timeout=1) do 
    #Default webdriver command here 
end 
rescue Timeout::Error 
    raise TimeoutError 
end 

SO не будет препятствовать мне сообщение более двух ссылок с моей патетически низкой репутацией, но исходный код для watir-webdriver находится на GitHub.


Я забыл поставить конкретный контекст, который показал мне, где время ожидания:

def test_rows_per_page() 
    begin 
    browser.element(:id => 'moar-rows').when_present.click 
    loading_element = element(:id => 'loading') 
    #loading_element.wait_while_present 
    assert_text = browser.element(:id => 'num-rows').text 

    browser.element(:id => 'less-rows').when_present.click 
    #loading_element.wait_while_present 
    puts loading_element.present? #=> true 
    sleep 1 
    puts loading_element.present? #times out here 
    sleep 1 
    puts loading_element.present? 

    diff_text = browser.element(:id => 'num-rows').text 
    if !(assert_text.eql? diff_text) 
     screen_capture() 
     assert_passed() 
    else 
     screen_capture() 
     assert_failed() 
    end 
    rescue 
    screen_capture() 
    increment_failed() #this is how I know it's timing out 
    end 
end 

закомментирована rescue блок, вот ошибка:

:in `eval': unknown error: Element is not clickable at point (550, 565). Other element would receive the click: <div id="loading-screen" class="loading-page-backdrop ng-scope" ng-if="pageLoading || gridLoading"></div> 
(Selenium::WebDriver::Error::UnknownError) 
(Session info: chrome=41.0.2272.76) 
(Driver info: chromedriver=2.6.232908,platform=Mac OS X 10.10.2 x86_64) 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/remote/response.rb:15:in `initialize' 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/remote/http/common.rb:59:in `new' 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/remote/http/common.rb:59:in `create_response' 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/remote/http/default.rb:66:in `request' 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/remote/http/common.rb:40:in `call' 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/remote/bridge.rb:640:in `raw_execute' 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/remote/bridge.rb:618:in `execute' 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/remote/bridge.rb:375:in `clickElement' 
from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.44.0/lib/selenium/webdriver/common/element.rb:54:in `click' 
from /Library/Ruby/Gems/2.0.0/gems/watir-webdriver-0.6.11/lib/watir-webdriver/elements/element.rb:132:in `click' 
from /Library/Ruby/Gems/2.0.0/gems/watir-webdriver-0.6.11/lib/watir-webdriver/wait.rb:122:in `method_missing' 
from /file.rb:208:in `rowsPerPage_next' 

Я m собирается попробовать browser.div(:id => 'loading-screen').wait_while_present, чтобы узнать, работает ли это. Трудно было вытащить либо id, либо class с HTML-страницы загрузки, поскольку она присутствует только во время загрузки. (Я спросил проявитель для идентификаторов, но мне не нравится подслушивания ее слишком много.)


Дополнительные примечания:

Моя главная проблема в том, что wait_while_present, кажется, не продолжать, если элемент ISN Нет. Вот почему я попробовал написать свою собственную janky версию, используя present?, но это также время ожидания, а не возвращение false, когда этого элемента нет. Я бы предпочел, чтобы версия Watir работала так, как это должно быть.

Я пробовал оба варианта как с id, так и с class для загрузки div, и это по-прежнему синхронизируется, а не продолжается, когда div нет.

я в настоящее время эти глобальные параметры ожидания, если это вообще отношение:

browser.driver.manage.timeouts.implicit_wait = 30 
browser.driver.manage.timeouts.page_load = 30 
Watir.default_timeout = 30 

present? должна возвращать true если элемент и существует, и видно, так что если нагрузка DIV не видно, то это должен просто вернуть false, правильно? Даже если он существует, но скрыт? Я действительно пытался понять это самостоятельно.

Пожалуйста, просто скажите мне, что я сумасшедший, и есть простой способ исправить это, например, переустановить Ruby или что-то в этом роде.

+0

Какая ошибка таймаута, которую вы получаете? Это также помогло бы, если бы скрипт показал, где вы звонили '.present? '. –

+0

Когда он заканчивается, он переходит в 'rescue', поэтому я просто получаю вывод из' increment_failed() '. Я прокомментировал строки 'wait_while_present' и запустил' puts load_element.present? (Timeout = 1) ', и он терпит неудачу после любого периода времени, который я установил для таймаута. –

+0

Я добавил еще один блок кода для большего контекста. –

ответ

0

Я думаю, что собираюсь сдаться и оставить sleep с.

(Игнорировать случайные изменения в class и id имена всей моей должности. Рекомендуем также snake_case против camelCase. Я не писал об этом так. Траст, что я успешно получаю к HTML элементов в вопросе.)

unknown error: Element is not clickable at point (550, 565). 
Other element would receive the click: <div id="dashboard-loading-screen" class="loading-page-backdrop ng-scope" 
ng-if="pageLoading || gridLoading"></div> (Selenium::WebDriver::Error::UnknownError) (Session info: chrome=41.0.2272.76) 

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

Также обратите внимание, что я не писал оригинальную версию этого теста, я просто пытаюсь заставить его утверждать правильно.

def dashboard_rowsPerPage_next(targetRows) 
    begin 
    dashboard_rowsPerPage_internal(targetRows) #click drop-down to choose num of rows/page 
    browser.scroll.to :bottom 
    beforeRowsText = $browser.div(:class => 'grid-rows-of-label').when_present.text.split(" ", 4).last #page 1 

    #I put this instead of wait_while_present 
    if (puts browser.html.include?("loading-page-backdrop ng-scope")) 
     Watir::Wait.while { browser.html.include? "loading-page-backdrop ng-scope"} 
    end 
    puts 'a' 
    puts browser.html.include?("loading-page-backdrop ng-scope") 
    puts browser.html.include?("loading-page-backdrop ng-scope") 

    #here's where I get the error message 
    browser.span(:class, "k-icon k-i-arrow-e").when_present.click 
    puts 'b' 
    puts browser.html.include?("loading-page-backdrop ng-scope") 

    if (puts browser.html.include?("loading-page-backdrop ng-scope")) 
     Watir::Wait.while { browser.html.include? "loading-page-backdrop ng-scope"} 
    end 

    puts browser.html.include?("loading-page-backdrop ng-scope") 
    puts 'c' 
    puts browser.html.include?("loading-page-backdrop ng-scope") 
    browser.scroll.to :bottom 
    puts browser.html.include?("loading-page-backdrop ng-scope") 
    afterRowsText = browser.div(:class => 'grid-rows-of-label').when_present.text.split(" ", 4).last #page 2 
    puts 'd' 
    Watir::Wait.while { browser.html.include? "dashboard-loading-screen"} 

    if (!(beforeRowsText.eql? afterRowsText)) #page 2 text should not be the same as page 1 text 
     screenCapture() 
     assertPassed() 
    else 
     screenCapture() 
     assertFailed() 
    end 
# rescue 
# screenCapture() 
# increment_failed() 
    end 
end 

Так что мой вывод: (добавлено комментарии для ясности)

true #should wait while loading image is visible before puts 'a' 
a 
true #this means the loading page is still visible, while isn't working 
true 
unknown error: Element is not clickable at point (550, 565). 
Other element would receive the click: <div id="dashboard-loading-screen" class="loading-page-backdrop ng-scope" 
ng-if="pageLoading || gridLoading"></div> (Selenium::WebDriver::Error::UnknownError) (Session info: chrome=41.0.2272.76) 

я проверил значение beforeRowsText и afterRowsText, и это правильно получать эти значения.

Так что я собираюсь сделать это вместо того, потому что я слаб:

def dashboard_rowsPerPage_next(targetRows) 
    begin 
    dashboard_rowsPerPage_internal(targetRows) #click drop-down to choose num of rows/page 
    browser.scroll.to :bottom 
    beforeRowsText = $browser.div(:class => 'grid-rows-of-label').when_present.text.split(" ", 4).last #page 1 
    sleep 10 
    browser.span(:class, "k-icon k-i-arrow-e").when_present.click 
    sleep 10 
    browser.scroll.to :bottom 
    afterRowsText = browser.div(:class => 'grid-rows-of-label').when_present.text.split(" ", 4).last #page 2 

    if (!(beforeRowsText.eql? afterRowsText)) #page 2 text should not be the same as page 1 text 
     screenCapture() 
     assertPassed() 
    else 
     screenCapture() 
     assertFailed() 
    end 
    rescue 
    screenCapture() 
    increment_failed() 
    end 
end 

Подождите нет, фигу. Он работает с 25 строками на странице, но я получаю ту же ошибку на 50 строк на страницу.

+0

Способ использования. 'include?' просто говорит вам, что эта вещь находится где-нибудь в HTML, она НЕ говорит вам, что вещь видима или скрыта по коду на стороне клиента и/или правилам CSS и т. д. этот метод является плохим выбором для отладки –

2

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

My main issue is that wait_while_present doesn't seem to continue if the element isn't present.

ЧТО поведение является

В то время как `.present? метод возвращает true или false (это то, что вы ожидаете от ЛЮБОГО метода, написанного на рубине, заканчивающегося вопросительным знаком), а не как различные функции ожидания. Кроме того, было бы разумно предположить, что они вернули истину или ложь, поскольку их имена методов не заканчиваются вопросительными знаками.

Цель тех функций ожидания является не ждать до тех пор, отведенного времени для ожидаемого состояния, что должен или обязательно манифеста (в противоположность может), а затем продолжить, или вызвать ошибку, если время ожидания истекло без выполнения условия.Вы можете:

  • Дождитесь элемента присутствовать
  • Дождаться элемент стать настоящей
  • Дождитесь условие, чтобы стать истинным
  • Подождите, пока условие не станет ложным

Презумпция при синхронизации с использованием этих методов заключается в том, что: если таймаут был превышен, сценарий не может быть надежно продолжен. Таким образом, тест терпит неудачу в этом пункте.

Эта работа по устранению ошибок (ака исключений) для отказа теста является довольно стандартным поведением для всех распространенных тестовых фреймворков практически на всех языках. Oucum, rspec, junit, minitest, nunit и т. Д. Утверждения/ожидания теста работают Точно так же, если утверждаемая вещь терпит неудачу, возникает ошибка. Структура «улавливает» ошибку, записывает детали как часть результатов теста, не проходит тест/сценарий и переходит к следующему. Если какой-либо метод, выполняемый во время теста, не работает, например, попытка щелкнуть кнопку, которая не существует, возникает ошибка, и тест завершается с ошибкой.

Для того, чтобы использовать эти методы, вам нужно будет обернуть вызов ожидания в коде обработки исключений, чтобы «спасти» ошибку, если метод завершил повышение ошибки. Или напишите свой собственный метод для выполнения ждет в ситуации, когда вы хотите подождать некоторое время для условия, чтобы мог манифест, а затем отвечать условно в соответствии с результатом, а не просто поднимать ошибку.

Работа с веб-страницей, которая имеет много динамического отображения на стороне клиента в ответ на действия пользователя, может быть очень сложной, когда нет простого способа узнать, занят ли клиентский код обновлением страницы, ожидая ответа к вызову службы или ожиданию ввода пользователя. Для этого нет никакого соглашения, и нет стандартного способа узнать, в чем дело. Если вам повезет, или ваш программист заботится о способности к тестированию, то они могут помочь вам с чем-то, что вы можете использовать, чтобы определить, в чем дело. Например, на многих сайтах есть значок прядильника, который отображается, когда клиентский код занят обновлением страницы или получением данных с серверов, и затем вы можете использовать видимость этого элемента, чтобы знать, когда ваш код должен ждать или когда он безопасен для продолжения ,

Имейте в виду, что эти методы могут принимать параметры, чтобы установить тайм-аут, и в некоторых случаях сообщение об ошибке .. делает использование, которое может значительно улучшить вашу способность устранять неполадки ..

, например, если у вас было действительно надежный вертушка, вы могли бы сделать что-то вроде этого, чтобы ждать до трех секунд для того, чтобы появиться, а затем до 10 секунд для того, чтобы уйти

b.element(:id => 'loading').wait_until_present(timeout=3) 
b.element(:id => 'loading').wait_while_present(timeout=10) 

Если мы хотим, чтобы не потерпеть неудачу, если не появится счетчик , и просто продолжайте идти, но проваливайте, если он был там больше 10 секунд, тогда вы могли бы сделать некоторые базовые exception handling вот так

begin 
    b.element(:id => 'loading').wait_until_present(timeout=3) 
rescue 
    puts "waited three seconds without seeing spinner" 
end 
b.element(:id => 'loading').wait_while_present(timeout=10) 

Без доступа к странице, которую вы тестируете, это трудно для кого-либо еще, чтобы сделать конкретные предложения о том, как вы можете получить код синхронизирован со страницей в прочном способом, который до сих пор производительным.

+0

Спасибо за подробное объяснение. Это моя первая стажировка, и я использую Watir около месяца, поэтому я делаю много проб и ошибок. У нас есть значок spinner (вот что означал 'element (: id =>" loading ")', и я использовал 'wait_while_present' в этом элементе, но я думаю, что счетчик не отображается достаточно последовательно для меня используйте его таким образом. –

+0

Да, это может быть сложно. то, что вы могли бы попробовать, это сделать вспомогательный метод «wait for spinner», он может включать в себя некоторые крошечные ожидания, такие как .1 или .2, чтобы дать время для его появления, а затем ждать пока присутствует, тогда, возможно, еще одно крошечное ожидание, а другое - настоящее время..в основном, чтобы быть уверенным, что это не вокруг. немного клочья. взаимодействовать вручную с сайтом и уделять действительно пристальное внимание задержкам между нажатиями, когда/если вы видите счетчик, сколько времени задержки между кликом и счетчиком. если он очень последователен, подождите до настоящего момента, а затем подождите, пока он может работать. –

+0

Я бы посоветовал вам посмотреть, можете ли вы поговорить с программистом, который владеет этой страницей, и спросить их, что происходит под обложками, когда эти вещи нажимаются, чтобы развернуть материал, а также спросите, как вы можете узнать, когда это безопасный для продолжения. возможно, у них будут некоторые идеи. Кроме того, я предполагаю, что вы изучаете Ruby в то же время, когда изучаете watir? –

0

Я изучаю рубин/ватир/огурец, и мне также нужно было подождать, что бы просто дать мне ложь, если пришло время. Я хотел подождать около 10 секунд, чтобы всплывающее окно появилось или нет, а затем продолжите код. Например, спящий режим 10 - это большой отход, если, например, всплывающее окно появляется менее чем за секунду.Как новичок, лучший способ, которым я нашел это, - использовать блоки If. Я проверяю, присутствует ли элемент, а если нет, я жду еще 3 секунды. в течение максимум 9 секунд. Это решило мою проблему.

Пример: я хочу проверить, появляется ли всплывающее слово со словом «Успех». Если да, то печатается «Пройден». Если он не появляется через 9 секунд, он печатает «Сбой».

if $browser.element(:text => "Success").exists? == False 
sleep 3 
end 

if $browser.element(:text => "Success").exists? == False 
sleep 3 
end 

if $browser.element(:text => "Success").exists? == False 
sleep 3 
end 

if $browser.element(:text => "Success").exists? == False 
puts "Failed" 
end 

if $browser.element(:text => "Success").exists? 
puts "Passed" 
end 

test continues 

Возможно, это поможет как-то!

Смежные вопросы