titusfortner / watirtight_comments

Allow comments on Watirtight blog
0 stars 1 forks source link

Locating Elements in Watir #4

Open titusfortner opened 8 years ago

titusfortner commented 8 years ago

Comments for: http://watirtight.com/2016/09/11/always-locate.html

abaird commented 8 years ago

Actually, now that I think of it, why would people using Watir want to implement a "Selenium approach to elements"? I thought that meant turning off "always_locate" - but isn't that what we just removed the ability to do?

Also, I don't think I'm understanding how "wait_until_stale?" is superior to the "wait_until" and "wait_while" methods. If I'm understanding you correctly, the "wait_until/while" methods rely on "exists?" to positively locate elements where the "stale?" approach just tells you when the DOM changes so you can check again. If stale? doesn't tell you that your specific element changed, don't you still have to check it again? Seems like it involves more calls that just a straight call to "wait_until/while" methods.

titusfortner commented 8 years ago

Yes, turning off #always_locate treats Watir elements like Selenium elements. This PR would remove that option. I wrote this article to clarify the potential downsides and non-backward compatibility issues, and to say why that PR should be accepted in spite of them. I don't think I explained the context or the ramifications of that PR very well when I proposed it, and I thought a more full explanation was in order.

As for #wait_until_stale... Let's say you implement this pattern in your tests:

Watir.always_locate = false
browser.title # => "First Page"
element_that_does_something_then_reloads_page.click
element_that_does_something_then_reloads_page.wait_while_present
browser.title # => "Second Page"

With the default setting the results would look like this:

Watir.always_locate = true
browser.title # => "First Page"
element_that_does_something_then_reloads_page.click
element_that_does_something_then_reloads_page.wait_while_present # => Watir::Wait::TimeoutError

The first one waits for the second page, because it will return "true" until the page has reloaded, then it will return "false" The second one times out because it will always re-look up the element and return true

So to maintain this pattern after the toggle has been removed, you change the wait_while_present to wait_until_stale:

Watir.always_locate = true
browser.title # => "First Page"
element_that_does_something_then_reloads_page.click
element_that_does_something_then_reloads_page.wait_until_stale
browser.title # => "Second Page"
akostadinov commented 7 years ago

What if element is removed from DOM just after stale? returns false? I don't think adding a method would resolve the safe interaction problem. IMO Watir should just execute the calls and if they fail, try to locate again. If cannot be located anymore, return some error.

While the construct with if stale? looks definitely nicer, it allows for a short time where a race condition could happen. The approach where one handles an exception is safer.

If you want to avoid the anti-pattern of using exceptions for flow control, then operations should never through exceptions but return result objects with information of whether operation succeeded and how it failed if it didn't.

titusfortner commented 7 years ago

We changed how it worked with Watir 6.4. After doing some performance runs on a remote service like Sauce Labs, it became obvious that we needed to drastically reduce our wire calls. So instead of "asking all of the questions ahead of time," we take the action and handle the error that is returned appropriately. Using "Exceptions as flow control" is "Bad," but in this case the (significant) performance improvement is worth that undesirability.

akostadinov commented 7 years ago

With 6.5.0 I've seen a number of Selenium::WebDriver::Error::StaleElementReferenceError and also Watir::Exception::UnknownObjectException when doing Watir::ElementCollection#to_a. That's why I wanted to comment. But now I notice in #571 that this should be fixed with dfc9e11. I will monitor if that's reproducible with 6.7.3 and will report back if I still can see such errors. Thank you!