TESTEROPS

A pragmatic approach to QA and OPS

ExecuteScript vs ExecuteAsyncScript in Selenium

Photo by Markus Spiske on <a href="https://www.pexels.com/photo/coding-script-965345/" rel="nofollow">Pexels.com</a>

One of the most common usage of pure JS powers in Selenium is the use of JavaScriptExecutor to achieve some desired functionality. An example of this is if you want to scroll down a web page explicitly, of if you want to modify the css properties of an element at run time then JavaScriptExecutor comes to your rescue.

In JavaScriptExecutor class in Selenium, there is a method called execute_script() or executeScript() for Java bindings- we’re familiar with this method. However, there is another method called the execute_async_script() [ executeAsyncScript() for Java bindings]. What is the purpose of that method?

The easiest answer one can think of is – it executes async js code. Thats the not the case. Let’s try to deep dive into this

execute_script( )

For an execute_script() method, JavaScript Executor runs the plain JS code with the reference to the present selected window or frame. The script given within the execute_script() method will run as the body of the unnamed function.

Inside the script, the document provided are used to point to the present document – the one active within the selected window or frame. Also, the local variables will not be present after as the script has completed execution. However, the global variables will be present.

Below are a set of rules that are applied on the given js function, if there is a corresponding return statement −

  • A webelement is returned for an HTML element.
  • A double is returned for a decimal number.
  • A long is returned for a non-decimal number.
  • A Boolean is returned for a Boolean number.
  • A string is returned for all the other cases.
  • A list of objects is returned following the above rules for an array.
  • If the value is null or there is nothing to return, a null is returned.

The arguments of the execute_script() method can be Boolean, string, web-element, list or a number. An exception is raised, if the arguments are not of these types. The arguments shall be available using the arguments keyword.

execute_async_script( )

For an execute_async_script() method, JavaScript Executor runs an asynchronous part of JS code, with the reference to the present selected window or frame.

In comparison to execute_script(), the scripts running with this method should clearly specify that they are completed by invoking a given callback.

The callback is always added as the last argument within the executed function that has been provided to execute_async_script(), and thus may be referenced with arguments[arguments.length - 1]. The first argument passed is used to get the script result. The values returned are handled in the similar way as the synchronous method -ie execute_script().

execute_async_script can be used for these following tasks−

  • To set the browser timeout.
  • To synchronize a test with an AJAX application.
  • To inject an XMLHttpRequest and wait for the result.

The arguments of execute_async_script() method can be Boolean, string, web element, list or a number. An exception is raised, if the arguments are not of these types. The arguments shall be available using the arguments keyword.

Difference between the two

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.

FWIW, use execute_async_script() when there needs to be a return value in the javascript function, but the return value needs some time to be processed and that return value won’t be available immediately.

This is especially necessary if you can’t poll for the result, but must get the result using a callback or promise (which you must translate to callback yourself).

However after reading the documents , both the execute_script and execute_async_script methods are blocking operations and will block the control flow in Selenium until they complete – either running off the end of the code for execute_script or when calling the ‘done callback’ with execute_async_script: “async” in the name signifies the signal mechanism used and does not mean/imply that the JavaScript code is actually executed asynchronously with respect to the WebDriver.

Sample code examples:

driver.execute_script('return arguments[0].tagName', el);
result = driver.execute_async_script("""
var done = arguments[0];
require(["foo"], function (foo) {
    done(foo.computeSomething());
});
""")

This is what my understanding of the difference between the two methods is. If you think there are some more differences, please feel free to comment and I’ll add them in the post.

%d bloggers like this: