development

카피 바라 모호성 해결

big-blog 2020. 8. 27. 08:15
반응형

카피 바라 모호성 해결


카피 바라의 모호성을 어떻게 해결합니까? 어떤 이유로 페이지에 동일한 값을 가진 링크가 필요하지만 오류가 발생하여 테스트를 만들 수 없습니다.

Failure/Error: click_link("#tag1")
     Capybara::Ambiguous:
       Ambiguous match, found 2 elements matching link "#tag1"

이것을 피할 수없는 이유는 디자인 때문입니다. 트윗 / 태그가 오른쪽에, 태그가 페이지 왼쪽에있는 트위터 페이지를 다시 만들려고합니다. 따라서 동일한 페이지에 동일한 링크 페이지가 표시되는 것은 불가피합니다.


내 해결책은

first(:link, link).click

대신에

click_link(link)

Capybara의 이러한 행동은 의도적이며 다른 대부분의 답변에서 제안한대로 수정해서는 안된다고 생각합니다.

2.0 이전 버전의 Capybara는 예외를 발생시키는 대신 첫 번째 요소를 반환했지만 나중에 Capybara의 관리자는 이것이 나쁜 생각이며이를 발생시키는 것이 더 낫다고 결정했습니다. 많은 상황에서 첫 번째 요소를 반환하면 개발자가 반환하고자하는 요소가 반환되지 않는 것으로 결정되었습니다.

여기에서 가장 많이 찬성 된 답변은 first또는 all대신 사용하는 것이 좋습니다 find.

  1. all그리고 first비록 페이지에 표시됩니다 같은 로케이터와 요소까지 기다리지 않는다 find대기 않습니다
  2. all(...).first그리고 first앞으로 이러한 로케이터와 다른 요소가 페이지에 표시 될 수 있다는 상황에서 당신을 보호하지 않으며 결과로 당신은 잘못된 요소를 찾을 수 있습니다

따라서 덜 모호한 다른 로케이터 를 선택하는 것이 좋습니다. 예를 들어 하나의 요소 만 일치하도록 ID, 클래스 또는 기타 css / xpath 로케이터별로 요소를 선택합니다.


모호성을 해결할 때 일반적으로 유용하다고 생각하는 몇 가지 로케이터는 다음과 같습니다.

  • find('ul > li:first-child')

    페이지에 first('ul > li')처음 li나타날 때까지 기다리는 것보다 더 유용 합니다.

  • click_link('Create Account', match: :first)

    first(:link, 'Create Account').click페이지에 하나 이상의 계정 만들기 링크가 나타날 때까지 기다리는 것보다 낫습니다 . 그러나 페이지에 두 번 나타나지 않는 고유 한 로케이터를 선택하는 것이 좋습니다.

  • fill_in('Password', with: 'secret', exact: true)

    exact: true Capybara에게 정확히 일치하는 항목 만 찾도록 지시합니다. 즉, "암호 확인"을 찾지 못합니다.


위의 솔루션은 훌륭하게 작동하지만 궁금한 사람들을 위해 다음 구문을 사용할 수도 있습니다.

click_link(link_name, match: :first)

여기에서 자세한 정보를 찾을 수 있습니다.

http://taimoorchangaizpucitian.wordpress.com/2013/09/06/capybara-click-link-different-cases-and-solutions/


새로운 답변 :

다음과 같은 것을 시도 할 수 있습니다.

all('a').select {|elt| elt.text == "#tag1" }.first.click

사용 가능한 Capybara 구문을 더 잘 사용할 수있는 방법이있을 수 있습니다.-라인을 따라 가지만 all("a[text='#tag1']").first.click올바른 구문을 직접 생각할 수 없으며 적절한 문서를 찾을 수 없습니다. 즉, 이상한 상황의 약간이 개 필요로 시작하는 말했습니다 <a>같은과 태그 id, class및 텍스트. find withinDOM의 적절한 세그먼트 를 수행 할 수 있으므로 다른 div의 자식 일 가능성이 있습니까? (HTML 소스를 보면 도움이 될 것입니다).


이전 답변 : (여기서 '# tag1'은 요소 id에 "tag1" 이 있음을 의미한다고 생각했습니다. )

어떤 링크를 클릭 하시겠습니까? 첫 번째 (또는 중요하지 않음)라면 할 수 있습니다.

find('#tag1').click

그렇지 않으면 할 수 있습니다

all('#tag1')[1].click

두 번째를 클릭합니다.


다음을 사용하여 첫 번째 것을 찾을 수 있습니다 match.

find('.selector', match: :first).click

그러나 중요한 것은 중복 출력 코드 냄새를 무시하는 깨지기 쉬운 테스트 로 이어지고 실패해야 할 때 계속 작동 하는 오 탐지 로 이어질 것입니다. 일치하는 하나를 제거했기 때문에이 작업 을 수행하고 싶지 않을 것입니다. 요소이지만 테스트는 행복하게 다른 것을 찾았습니다.

더 나은 방법은 다음을 사용하는 것입니다 within.

within('#sidebar') do
  find('.selector).click
end

This ensures that you're finding the element you expect to find, while still leveraging the auto-wait and auto-retry capabilities of Capybara (which you lose if you use find('.selector').click), and it makes it much clearer what the intent is.


To add to the existing body of knowledge here:

For JS tests, Capybara has to keep two threads (one for RSpec, one for Rails) and a second process (the browser) in sync. It does this by waiting (up to the configured maximum wait time) in most matchers and node-finding methods.

Capybara also has methods that don't wait, primarily Node#all. Using them is like telling your specs that you'd like them to fail intermittently.

The accepted answer suggests page.first('selector'). This is undesirable, at least for JS specs, because Node#first uses Node#all.

That said, Node#first will wait if you configure Capybara like so:

# rails_helper.rb
Capybara.wait_on_first_by_default = true

This option was added in Capybara 2.5.0 and is false by default.

As Andrei mentioned, you should instead use

find('selector', match: :first)

or change your selector. Either will work well regardless of config or driver.

To further complicate things, in old versions of Capybara (or with a config option enabled), #find will happily ignore ambiguity and just return the first matching selector. This isn't great either, as it makes your specs less explicit, which I imagine is why no longer the default behavior. I'll leave out the specifics because they've been discussed above already.

More resources:


Due to this post, you can fix it via "match" option:

Capybara.configure do |config|
  config.match = :prefer_exact
end

As considering all the above options, you can try this too

find("a", text: text, match: :prefer_exact).click

If you are using cucumber, you can follow this too

You can pass the text as a parameter from the scenario steps which can be generic step to reuse again

Something like When a user clicks on "text" link

And in step definition When(/^(?:user) clicks on "([^"]*)" (?:link)$/) do |text|

This way, you can reuse the same step by minimizing the lines of code and would be easy to write new cucumber scenarios


To avoid ambiguous error in cucumber.

Solution 1

first("#tag1").click

Solution 2

Cucumber features/filename.feature --guess

참고URL : https://stackoverflow.com/questions/13132506/capybara-ambiguity-resolution

반응형