Using webdriver-sync on multiple devices

Running web tests on multiple devices

Webdriver-sync can be used to drive tests on the local machine, on remote machines running their own webdriver implementation or on IOS and Android mobile devices. Note that the scripts themselves do not need to change for each environment, webdriver abstracts away from all the underlying differences.

Running tests remotely.

Normally you would instantiate a browser locally something like this:

    var wd = require("webdriver-sync");
    var caps = new wd.DesiredCapabilities["chrome"]();
    var driver = new wd["ChromeDriver"](caps);

To instantiate a browser on a remote machine (which has the appropriate webdriver installed) just include the machine's IP address and request a RemoteWebDriver:

    var wd = require("webdriver-sync");                
    var caps = new wd.DesiredCapabilities["internetExplorer"]();
    var driver = new wd["RemoteWebDriver"]
        ("http://[remote machine ip address]:4444/wd/hub", caps);

Running tests on IOS

This is a bit more complicated. To run a test on an iPad for instance, you will need some Mac hardware running OSX. Connect the iPad using the USB cable.

You will need to enable developer mode on the iPad via Xcode on the Mac. In Xcode open the devices organiser, select the iPad and click "Use for Development"

Before running any tests, launch ios-server-standalone-n.n.n-SNAPSHOT.jar in iTerm on the Mac with the -beta flag. You should now see the iPad connected via port 5555 (remember 4444 is already used for the local webdriver on the Mac).

You can now run tests on the iPad from the Mac (or any other machine using the remote driver option):

    var wd = require("webdriver-sync");                                
    var caps = new wd.DesiredCapabilities["ipad"]();
    var driver = new wd["RemoteWebDriver"]
        ("http://[Mac ip address]:5555/wd/hub", caps);

Sometimes you can see that the tests are running because there is output in iTerm but you can't see anything happen on the iPad. Just open another tab and you should be able to see the tests running.

Remember there is no local file system access on the iPad so there is no way to run tests involving uploading or downloading files.

If you don't have an iPad, you can use the same process to run the tests in IOS Simulator.

Running tests on Android

Install chromedriver and the Android SDK using these instructions.

Attach the android device with USB and put it into developer mode using the 7-tap method.

Then start the adb server and chromedriver on your development box.

    adb start-server


The android device will now be available as a RemoteWebDriver:

    var chromeOptions = new wd.ChromeOptions();
    chromeOptions.setExperimentalOption("androidPackage", "");
    caps = new wd.DesiredCapabilities["chrome"]();
    caps.setCapability("chromeOptions", chromeOptions);
    driver = new wd["RemoteWebDriver"]("", caps);    

You will see the correct port number to use in that last line when you start chromedriver.

The test will now run in Chrome on the android device

Note that some window methods will return errors, e.g. you cannot do this on android:


Running tests in Chrome's Device Emulator

Chrome Developer Tools has a device emulation mode that changes the screen dimensions and user agent string to reflect a mobile device. With a bit of work, we can exploit this in our scripts.

    var utils = require("webdriver-sync/src/utils");
    //pass the device name in as a string, e.g "Apple iPhone 5"
    var mobileDevice = utils.objectToMap({"deviceName": deviceName});
    chromeOptions = new wd.ChromeOptions();
    chromeOptions.setExperimentalOption("mobileEmulation", mobileDevice);
    caps = new wd.DesiredCapabilities["chrome"]();
    caps.setCapability("chromeOptions", chromeOptions);
    driver = new wd["ChromeDriver"](caps); 

Chrome will now open but switched to the chosen device emulation mode.

Note that this means you will have to adapt your scripts to cope with hamburger menus.

Network throttling with ChromeDriver

ChromeDriver 2.24 provides the ability to set network conditions as seen in the Developer Tools device tab.

The interface is not exposed yet in webdriver-sync but with a bit of work, we can access the settings via the JSON Wire Protocol.

    var sh = require("child_process").execSync;                

    function setNetwork(networkType) {
        var sessId = driver.getSessionId().toString();
        console.log("SESSION " + sessId);
        var port = sh("netstat -ltpn | grep chromedriver").toString().match(/\d+)/)[1];
        console.log("PORT " + port);
        console.log("SETTING NETWORK TO " + networkType);
        sh(`wget -q -O- http://localhost:${port}/session/${sessId}/chromium/network_conditions 
           --post-data='{"network_name": "${networkType}"}'`);

    //we need to test using a mobileDevice as set up above with an additional capability:
    caps.setCapability("networkConnectionEnabled", true);

Next: Readable test scripts