Understanding execute async script in Selenium

后端 未结 2 764
粉色の甜心
粉色の甜心 2020-11-28 09:10

I\'ve been using selenium (with python bindings and through protractor mostly) for a rather long time and every time I needed to execute a javascript code, I\'v

2条回答
  •  -上瘾入骨i
    2020-11-28 10:11

    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.

提交回复
热议问题