Selenium Grid

Selenium Grid:

Well, I have experienced the following scenarios while setting up the grid environment for the first time. 

Here it is, I have two machine, say '10.19.137.247' (test machine) and 192.168.1.113 (test dev machine) so to start the hub on test machine I have run the following command:

On Test Machine:

    java -jar selenium-server-standalone.jar -role hub
The following message or information appeared on command line as a result
Mar 10, 2014 2:57:03 AM org.openqa.grid.selenium.GridLauncher main
INFO: Launching a selenium grid server
2014-03-10 02:57:26.332:INFO:osjs.Server:jetty-7.x.y-SANPSHOT
2014-03-10 02:57:26.395:INFO:osjsh.ContextHandler:started o.s.j.s.ServletContextHandler{/,null}
2014-03-10 02:57:26.410:INFO:osjs.AbstractConnector:Started SocketConnector@0.0.0.0:4444     

On Test Dev machine:

 java -jar selenium-server-standalone -Dwebdriver.chrome.driver=C:\Users\Fayaz\Downloads\chromedriver.exe -role webdriver -hub http://10.19.137.247/grid/register
The following message or information appeared on command line as a result
Mar 10,  2014 12:30:36 PM org.openqa.grid.selenium.GridLauncher main
INFO: Launching a selenium grid node
Mar 10, 2014 12:30:39 PM org.openqa.grid.internal.utils.SelfRegisteringRemote startRemoteServer
WARNING: error getting the parameters from the hub. The node may end up with wrong timeouts. Connection refused: connect
12:30:39.255 INFO - Java: Oracle Corportation 24.45-b08
12:30:39.263 INFO - OS:Windows 7 6.1 x86
12:30:39.295 INFO - v2.39.0, with Core v2.39.0. Built from revision ff23eac
12:30:39.565 INFO - Default driver org.openqa.selenium.iphone.IPhoneDriver registration is skipped: registration capabilities Capabilites [{platform=MAC, browserName=iPhone, version=}] does not match with current platform: VISTA
12:30:39:565 INFO - Default driver org.openqa.selenium.iphone.IPhoneDriver registration is skipped:
registration capabilities Capabilities [{platform=MAC, browserName=iPad, version=}] does not match with current platform: VISTA
12:30:39.648 INFO - RemoteWebDriver instances should connect to : http://127.0.0.1:5555/wd/hub
12:30:39.649 INFO - Version Jetty/5.1.x
12:30:39.650 INFO - Started HttpContext[/selenium-server/driver./selenium-server/driver]
12:30:39.651 INFO - Started HttpContext[/selenium-server,/selenium-server]
12:30:39:652 INFO - Started HttpContext[/,/]
12:30:39:654 INFO - Started org.openqa.jetty.jetty.servlet.ServletHandler@12132a6
12:30:39.654 INFO - Started HttpContext[/wd,/wd]
12:30:39.657 INFO - Started SocketListener on 0.0.0.0:5555
12:30:39.658 INFO - Started Started org.openqa.jetty.jetty.Server@a4b9da
12:30:39.661 INFO - using the json request : {"class":"org.openqa.grid.common.RegistrationRequest","capabilities":[{"platform":"VISTA","seleniumProtocol":"Selenium","browserName":"*firefox","maxInstances":5},{"platform":"VISTA","seleniumProtocol":"Selenium","browserName":"*googlechrome","maxInstances":5},{"platform":"VISTA","seleniumProtocol":"seleniumProtocol":"WebDriver","browserName":"chrome","maxInstances":1},{"platform":"VISTA","seleniumProtocol":"WebDriver","browserName":"internet explorer","maxInstances":1}],"configuration":{"port":5555,"register":true,"host":"192.168.1.113","proxy":"org.openqa.grid.selenium.proxy.DefaultRemoteProxy","maxSession":5,"role":"node","hubHost":"10.19.137.247","registerCycle":5000,"hub":"http://10.19.137.247/grid/register","hubPort":-1,"url":"http://192.168.1.113:5555","remoteHost":"http://192.168.1.113:5555"}}
12:30:39.664 INFO - Starting auto register thread. Will try to register every 5000 ms.
12:30:39.664 INFO - Registering the node to hub :http://10.19.137.247:-1/grid/register
12:30:41.466 INFO - couldn't register this node : Error sending the registration request.
12:30:48.264 INFO - couldn't register this node : Hub is down or not responding: Connection refused: connect
If we observer on the test machine to verify the status of the selenium web server whether the client / node is connected or not, in other words when no node connects to hub using selenium grid, it will looks like in the screen shot

When no nodes connects to a hub using selenium grid then the server details displayed


This error has been resolved after I corrected the command to connect the hub from my test dev machine, and the changed command is
java -jar selenium-server-standalone.jar -Dwebdriver.chrome.driver=C:\Users\Fayaz\Downloads\chromedriver.exe -role webdriver -hub http://10.19.137.247:4444/grid/register

The difference here is I am using port number ':4444' after test machine URL

After connecting to the server, we can verify the status of the selenium web server whether the client / node is connected or not, it will looks like in the screen shot


When a node connects to hub using selenium grid then the list of details displayed


The path in browser to see list of clients or nodes connected to a hub at server / hub side is,
 localhost:4444/grid/console
For a beginner most common and exception can occur as follows, part of exception pasted
Caused by: java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.chrome.driver system property;
For more info please find the source here

To handle ssl or certification errors on a remote browser, I have used the following code and it worked like a charm

For IE or Chrome:
  remoteWebdriver.navigate().to("javascript:document.getElementById('overridelink').click()");
//I assume you have already had a wed driver reference called 'remoteWebdriver'


Now, to take screen shot of the remote test script execution, you can find the code in this selenium webdriver cheat code or from here

Update :


From the latest release of selenium 3.x, if we use above command to register client to remote hub then we get the following exception

Exception in thread "main" com.beust.jcommander.ParameterException: Unknown option: -Dwebdriver.chrome.driver=C:\Users\Fayaz\Downloads\chromedriver.exe
        at com.beust.jcommander.JCommander.parseValues(JCommander.java:742)
        at com.beust.jcommander.JCommander.parse(JCommander.java:282)
        at com.beust.jcommander.JCommander.parse(JCommander.java:265)
        at com.beust.jcommander.JCommander.<init>(JCommander.java:210)
        at org.openqa.grid.selenium.GridLauncherV3$3.setConfiguration(GridLauncherV3.java:267)
        at org.openqa.grid.selenium.GridLauncherV3.buildLauncher(GridLauncherV3.java:155)
        at org.openqa.grid.selenium.GridLauncherV3.main(GridLauncherV3.java:75)




So the command to register a node / client is changed as follows:

                        java -jar selenium-server-standalone-3.3.1.jar -role node -hub http://<hub_ip>:4444/grid/register -port 4444

Browser Functions

Handling Browser Functionality

Scroll Down:

/**
 * Scroll to the bottom of a page and sleep for 10 seconds
 * 
 */
public static void scrollDown() {
((JavascriptExecutor) SeleniumAction.getDriver())
.executeScript("scroll(0, 250)");
sleep(10); // Customized sleep method
}

Scroll Up:

/**
 * Scroll to the top of a page and sleep for 10 seconds
 * 
 */
public static void scrollUp() {
((JavascriptExecutor) SeleniumAction.getDriver())
.executeScript("scroll(250, 0)");
sleep(10); // Customized sleep method
}


Scroll Upto an Element:

/**
 * Scroll to an web element to make it display on screen 
 *  
 * @param element
 */
public static void scrollToAnElement(WebElement element) {
if (isElementExists(element)) {
((Locatable) element).getCoordinates().inViewPort();
sleep(5); // Customized sleep method
}

}

Maximize a web browser:
/**
* Maximize a browser window
*/
public void maximizeBrowserWindow(){
       driver.manage().window().maximize();
}

Refresh a browser:
/**
* Refresh a browser window
*/
//Method #1:
public void refreshBrowserWindow(){
       driver.navigate().refresh();
}

//Method #2:
public void refreshBrowserWindow(){
       driver.get(driver.getCurrentUrl());
}

// Method #3:
public void refreshBrowserWindow(){
      driver.navigate().to(driver.getCurrentUrl());  
}

//Method #4:
public void refreshBrowserWindow(WebDriver driver){
      Actions refreshAction = new Actions(driver);
      refreshAction.keyDown(Keys.CONTROL).sendKeys(Keys.F5).perform();
}

Handling an alert:
/**
 * Handling an alert dialog 
 * 
 *@param discard
 */
public void handleAlert(boolean discard){
     Alert alertHandler =    driver.switchTo().alert();
     if(discard){
          alertHandler.dismiss();
     } else {
           alertHandler.accept();
     }
}

Take a screenshot:

/**
 * Takes a screen shot and save with the given file name
 *  
 * @param fileName
 * @throws IOException
 */

public static void takeScreenshot(String fileName) throws IOException {
File screenshot = ((TakesScreenshot) SeleniumAction.getDriver())
.getScreenshotAs(OutputType.FILE);
String dirPath = ScriptsExecuted.getRFTLogDirectory()
+ fileName
+ new SimpleDateFormat("MM-dd-yyy_HH:ss")
.format(new GregorianCalendar().getTime() + ".jpg");
FileUtils.moveFile(screenshot, new File(dirPath));
}

// For taking a screen shot on remote web driver, source

/**
  *  RemoteWebDriver does not implement the TakesScreenshot class
  *  if the driver does have the Capabilities to take a screenshot

  *  then Augmenter will add the TakesScreenshot methods to the instance
  */
public void myTest() throws Exception {
        WebDriver driver = new RemoteWebDriver(
                                new URL("http://localhost:4444/wd/hub"), 
                                DesiredCapabilities.firefox());
        
        driver.get("http://www.google.com");
        WebDriver augmentedDriver = new Augmenter().augment(driver);
        File screenshot = ((TakesScreenshot)augmentedDriver).
                            getScreenshotAs(OutputType.FILE);
}


Verification of an element existence:

/**
 * Method to verify whether desired web element is exists or not by handling
 * exceptions
 * 
 * @param element
 * @return
 */
public static boolean isElementExists(WebElement element) {
boolean result = false;
try {
if (element != null) {
result = element.isDisplayed();
}
} catch (NoSuchElementException noElementExecption) {
result = false;
} catch (StaleElementReferenceException staleElementException) {
return false;
}
return result;
}


Wait For page to load

void waitForLoad(WebDriver driver) {
    ExpectedCondition<Boolean> pageLoadCondition = new
        ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver driver) {
                return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
            }
        };
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(pageLoadCondition);

}


Validate Image Loaded properly

/**
  * Import statements, 
  */
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;

public void validateInvalidImages() {
try {
invalidImageCount = 0;
List<WebElement> imagesList = driver.findElements(By.tagName("img"));
System.out.println("Total no. of images are " + imagesList.size());
for (WebElement imgElement : imagesList) {
if (imgElement != null) {
verifyimageActive(imgElement);
}
}
System.out.println("Total no. of invalid images are " + invalidImageCount);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}

public void verifyimageActive(WebElement imgElement) {
try {
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(imgElement.getAttribute("src"));
HttpResponse response = client.execute(request);
// verifying response code he HttpStatus should be 200 if not,
// increment as invalid images count
if (response.getStatusLine().getStatusCode() != 200)
invalidImageCount++;
} catch (Exception e) {
e.printStackTrace();
}

}