When should I use execute_async_script()
instead of the regular execute_script()
?
When it comes to checking conditions on the browser side, all checks you can perform with execute_async_script
can be performed with execute_script
. Even if what you are checking is asynchronous. I know because once upon a time there was a bug with execute_async_script
that made my tests fail if the script returned results too quickly. As far as I can tell, the bug is gone now so I've been using execute_async_script
but for months beforehand, I used execute_script
for tasks where execute_async_script
would have been more natural. For instance, performing a check that requires loading a module with RequireJS to perform the check:
driver.execute_script("""
// Reset in case it's been used already.
window.__selenium_test_check = undefined;
require(["foo"], function (foo) {
window.__selenium_test_check = foo.computeSomething();
});
""")
result = driver.wait(lambda driver:
driver.execute_script("return window.__selenium_test_check;"))
The require
call is asynchronous. The problem with this though, besides leaking a variable into the global space, is that it multiplies the network requests. Each execute_script
call is a network request. The wait
method works by polling: it runs the test until the returned value is true. This means one network request per check that wait
performs (in the code above).
When you test locally it is not a big deal. If you have to go through the network because you are having the browsers provisioned by a service like Sauce Labs (which I use, so I'm talking from experience), each network request slows down your test suite. So using execute_async_script
not only allows writing a test that looks more natural (call a callback, as we normally do with asynchronous code, rather than leak into the global space) but it also helps the performance of your tests.
result = driver.execute_async_script("""
var done = arguments[0];
require(["foo"], function (foo) {
done(foo.computeSomething());
});
""")
The way I see it now is that if a test is going to hook into asynchronous code on the browser side to get a result, I use execute_async_script
. If it is going to do something for which there is no asynchronous method available, I use execute_script
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…