При написании тестовой среды/тестов с использованием Capybara + RSpec я столкнулся с этим предложением для тестирования НЕ существования элемента:
expect(page).to have_no_button('Save') # OK
expect(page).not_to have_button('Save') # Bad
Я был смущен, почему, пока не увидел, что было сказано:
Use should have_no_* versions with RSpec matchers because should_not have_* doesn’t wait for a timeout from the driver.
Это правда? Если нет... не имеет ли смысл с точки зрения объектной модели страницы иметь метод для проверки и возврата, существует ли <element>
(я обычно использую .visible?
), чтобы вы могли использовать сопоставитель rspec для выполнения expect(page_object).to be_method_visible
или expect(page_object).not_to be_method_visible
?
В отличие от необходимости писать 2 отдельных метода в объектах вашей страницы (если это правда, что not_to
не будет ждать)
В качестве примера моих методов утверждения в моей объектной модели страницы, вот что я делаю для проверки «ссылки для выхода»
def logged_in?
logout_text.visible?
end
private
def logout_text
find 'a', text: 'Log Out'
end
И тогда в спецификации я бы сказал:
expect(page_object).to be_logged_in
Поэтому я бы использовал что-то подобное для других элементов.
Я не знаю, где вы наткнулись на это предложение (может быть, оно действительно очень старое), но для любой «последней» версии Capybara (по крайней мере, за последние 4 года) при использовании предоставленных Capybara сопоставителей это неверно.
Предполагая, что have_button
и have_no_button
являются предоставленными Capybara сопоставителями (а не встроенным have_xxx => has_xxx?
сопоставителем RSpecs, вызывающим has_button?
метод, который вы определили на своем объекте страницы), два приведенных вами примера
expect(page).to have_no_button('Save')
expect(page).not_to have_button('Save')
будет вести себя одинаково. Они оба проверяют наличие кнопки и возвращаются, когда ее не существует, или вызывают исключение, если Capybara.default_max_wait_time секунд прошло, а кнопка все еще видна на странице.
@msmith1114 msmith1114 Проблема с асинхронным поведением браузера заключается в том, что вам нужно поведение ожидания для стабильности теста. Если вы вызываете логические методы, это будет означать, что иногда вы ожидаете, что оно будет истинным, а иногда ложным - какое из них следует ожидать? С утверждениями/ожиданиями Капибара может точно знать, чего ждать. Если вы используете логические методы, вы, вероятно, захотите отключить в них ожидание, а затем самостоятельно обрабатывать ожидание/стабильность.
@msmith Чтение вашего обновленного вопроса - метод logged_in?
никогда не будет работать - если не существует ссылки с «Выйти из системы» (должно быть выполнено как find_link('Log Out')
, а не как селектор CSS) (или если ссылка не видна), find поднимется исключение - так что он никогда не доберется до вызова visible?
на нем
Как мне тогда структурировать его в объекте страницы? Я пытаюсь не использовать методы селена/капибары в реальной спецификации. Я хочу иметь метод, который я могу утверждать (внутри самой тестовой спецификации, а не иметь утверждение в объекте страницы)
@ msmith1114 Именно поэтому объект страницы так основан на мнении. Для того, что вы хотите, вы, вероятно, хотите написать свои собственные сопоставители RSpec (или, по крайней мере, иметь методы, которые возвращают экземпляры сопоставителей Capybara) и включить их в свой тестовый класс, т.е. вам нужно получить метод с именем be_logged_in
доступен в вашем тестовом примере, который возвращает Capybaras have_link('Log Out')
, чтобы вы могли затем вызвать expect(page).to be_logged_in
- есть много способов, которыми вы могли бы закончить с этим, проще всего, вероятно, перезаписать стандартное поведение RSpecs be_xxx
Похоже, я вроде как просто против правдивости, верно? Или, если он терпит неудачу, он на самом деле не возвращает истинное или ложное значение из этих методов, если элемент не существует, поэтому он всегда будет говорить, что он успешен? (Потому что сейчас кажется, что to be_method_true
, по крайней мере, не «проваливается» при тестировании)
@ msmith1114 Я не знаю, что вы имеете в виду под to be_method_true
, но все может работать нормально, пока у вас не будет асинхронного поведения на странице — или вы можете возвращать правдивый объект, который никогда не выйдет из строя, или сообщения об ошибках при сбое могут выглядеть как будто они не имеют ничего общего с тем, что вы утверждаете. т.е. Ваш 'is_logged_in?' метод никогда не может вернуть false
, поэтому expect(page).to be_logged_in
вполне может работать, если элемент находится на странице, но expect(page).not_to be_logged_in?
не может работать.
Эти примеры были взяты с сайта, который я видел. В основном я хочу проверить, что кнопка НЕ существует. Я занимаюсь объектной моделью страницы... поэтому мне имело смысл создать метод, который возвращает логическое значение, если кнопка
visible?
, а затем просто использовать.to be_method
или.not_to be_method
. Возможно, я неправильно использую сопоставители rspec, так как я используюto be
вместоto have
, но я возвращаю логическое значение из моих методов (редактирование сделано в посте)