Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make parallel requests to a Selenium Webdriver grid

I'm trying to use a selenium server grid to run multiple commands in parallel. Here is my first test code:

var webdriver = require('selenium-webdriver');

for(var u = 0; u < 3; u++) {
    makeScreenshot('foo/test' + u + '.png');
}

function makeScreenshot(path) {

    var driver = new webdriver.Builder().forBrowser('firefox').usingServer('http://someurl:44111/wd/hub/').build();

    console.log('Get');
    driver.get('http://www.somepage.com').then(function() {

        console.log('Screenshot');
        driver.takeScreenshot().then(function(data){

            console.log(path);
            //var decodedImage = new Buffer(data, 'base64')

            driver.quit();

        });
    });

}

That is the result:

Get
Get
Get
Screenshot
foo/test0.png
Screenshot
foo/test1.png
Screenshot
foo/test2.png

screenshot of requests

The "Get" appears immediately in sequence, "driver.get" creates a promise. My idea here is that the three requests are made asynchronously and thus appear almost simultaneously. But as you can see in the screenshot they will be made one after the other. The grid definitely has enough selenium instances so why isn't the driver working in parallel? It seems to me that "new webdriver.Builder()" creates some kind of singleton that doesn't work async but waits for the previous request to finish!?

Thanks for any help!

like image 683
Gibbonson Avatar asked Feb 29 '16 14:02

Gibbonson


1 Answers

The answer may be multiple control flows:

WebDriverJS supports defining "parallel" flows using webdriver.promise.createFlow(). This function accepts a callback which will be passed the newly created flow. Tasks scheduled within this flow will be synchronized with each other, but will remain independent of any other control flows. Each call to createFlow() returns a promise that will resolve when the flow has completed.

The example at the end of the chapter (which I'll quite verbatim) shows multiple Google search terms being tested concurrently:

var terms = [
   'javascript',
   'selenium',
   'webdriver'
];

var flows = terms.map(function(term) {
 return webdriver.promise.createFlow(function() {
   var driver = new webdriver.Builder().build();

   driver.get('http://www.google.com');
   driver.findElement(webdriver.By.name('q')).sendKeys(term);
   driver.findElement(webdriver.By.name('btnG')).click();
   driver.getTitle().then(function(title) {
     if (title !== (term + ' - Google Search')) {
       throw Error('Unexpected title: ' + title);
     }
   });
 });
});

webdriver.promise.fullyResolved(flows).then(function() {
 console.log('All tests passed!');
});

It should be easy enough to add your custom driver build and lookups into that example. Perhaps the following:

var flows = [0,1,2,3].map(function(index) {
 return webdriver.promise.createFlow(function() {
   var driver = new webdriver.Builder().forBrowser('firefox').usingServer('http://someurl:44111/wd/hub/').build();

   console.log('Get');
   driver.get('http://www.somepage.com').then(function() {

        console.log('Screenshot');
        driver.takeScreenshot().then(function(data){

            console.log('foo/test' + index + '.png');
            //var decodedImage = new Buffer(data, 'base64')

            driver.quit();
        });
    });
 });
});
like image 165
Andrew Regan Avatar answered Oct 25 '22 03:10

Andrew Regan