6 ms·
FWIW the most consistent (as in non-flaky) selenium tests I've worked with used hidden DOM elements to synchronize the selenium driver with the JS code: http:/
by stephen 9y ago
FWIW the most consistent (as in non-flaky) selenium tests I've worked with used hidden DOM elements to synchronize the selenium driver with the JS code:
http://www.draconianoverlord.com/2011/10/14/sane-selenium-testing.html http://www.draconianoverlord.com/2011/10/14/sane-selenium-te...
Basically every JS ajax call (or JS promise, though we didn't use any of those at the time) would update a hidden DOM element's inner text, e.g. the `#pendingAjaxRequests` inner text would go to 1, or 2, then back to 0 when the AJAX response came back (ideally you do this instrumentation in a single place in your app).
Then on the selenium side, after every button click/other action, we'd wait until those counters went back down to zero.
This post-action waiting (waiting for the app to "settle" after invoking actions) vs. pre-action waiting (...well, this the element I want to click on available yet? Hm...no...) was very reliable.
- gowan 9y agosounds like an interesting pattern. it would be nice to have a browser extension that abstracts the pattern in the browser.
- cdubzzz 9y agoInteresting! Thanks for the reference. I think all the waiting I have dealt with is server (vs. animation) as well. I'll have to play around with this idea...
- whatnotests 9y agoThat's not how it's suppose to work. If your program can tell when something happens then your user should be able to as well. Please, let's not consider this to be a positive design - rather this is smell. Check your UX for usability, then proceed with behavior testing.
- zootam 9y ago>There are a variety of ways of doing this, but you basically need a choke point in your application where all AJAX requests go through. Does wrapping the XMLHTTPrequest object to get this functionality still count as sane?
- stephen 9y agoYep! We technically had our own layer on top of XMLHTTPRequest to use a centralized slice point instead, but AFAIK wrapping it directly would be great too.
- hinkley 9y agoI've done this twice. It's the only way I've ever gotten any sanity out of Selenium.
- danidiaz 9y ago> I've done this twice. It's the only way I've ever gotten any sanity out of Selenium. What are the benefits of this approach vs. explicitly waiting for the things that should appear in the page?
- yebyen 9y agoWhat do you think of this approach instead: http://cabeca.github.io/blog/2013/06/16/waiting-for-completed-ajax-in-capybara-and-other-tricks/ http://cabeca.github.io/blog/2013/06/16/waiting-for-complete... When I did this type of workaround (I have not needed to write one of these for a while) I found it was a problem for control flow that I needed to know if the action actually started and finished, not just whether it was currently in progress. I used an .ajax-processing class that I added at the start of the request, and removed when the request came back with a callback. While I can see the advantage of pendingAjaxRequests instead (you could have more than one going at a given time, and my .ajax-processing breaks down there), it still seems like you could have a problem as the browser JS is not running in the same process as your server or your test executor. Your next line of code might run before the browser increments the inner text, or starts the XHR. You could pass control flow on thinking that the event has already completed, when in reality it hasn't even started yet. The 2013 article I linked seems to have a more robust model for tracking requests, it's just two variables, but it would seem to handle this problem with perfect reliability.
- stephen 9y agoThe approach you linked to looks good to me. I hadn't seen that before; thanks for sharing it! > Your next line of code might run before the browser increments the inner text, or starts the XHR. Yeah, that is true in theory, but we never had a problem with that--my mental model was that if the Selenium process issued a click, and it got sent to the browser, any "onclick" behavior would fire within that immediate event loop (and for our app that's where we issued any AJAX calls, immediately within that event loop), tick up the hidden DOM count, before the webdriver code that's sitting within the browser sends back the response to Selenium client. I've not examined the webdriver impls of each various browser, but AFAICT my theory matches what we saw at the time (in google/firefox with native events enabled). I'd be very interested to hear from someone authoritatively on whether this theory is actually correct. Also, if you have a JS-side persistence layer that does AJAX calls in separate event loops, e.g. with setTimeout, then yeah I could see this being an issue and would necessitate a more deliberate approach (like your linked post, which I like).
- 9y ago