Friday, May 10, 2013

Wait for AJAX call to complete in WebDriver

Sometimes in our web application only part of the web page gets loaded upon certain actions, at that time actually an ajax call happens and depending upon the ajax response the page part loads. So in this case we need to wait till the ajax call is completed to test anything on that part of the webpage, if you don't want to do that by waiting for a specific element to be available. Below is the code that waits till the ajax calls completed:
/**
 * Waits until there are no more active ajax connection and until the
 * specified timeoutInSeconds is timeout
 * 
 * @param timeoutInSeconds
 */
public void waitForAjax(long timeoutInSeconds) {
 log.info("Checking active ajax calls by calling jquery.active");
 try {
  if (driver instanceof JavascriptExecutor) {
   JavascriptExecutor jsDriver = (JavascriptExecutor) driver;

   for (int i = 0; i < timeoutInSeconds; i++) {
    Object numberOfAjaxConnections = jsDriver
      .executeScript("return jQuery.active");
    // return should be a number
    if (numberOfAjaxConnections instanceof Long) {
     Long n = (Long) numberOfAjaxConnections;
     log.info("Number of active jquery ajax calls: " + n);
     if (n.longValue() == 0L)
      break;
    }
    Thread.sleep(1000);// 1 second sleep
   }
  } else {
   log.error("Web driver: " + driver
     + " cannot execute javascript");
  }
 } catch (Exception e) {
  log.error("Failed to wait for ajax response: " + e);
 }
}
In this code snippet we are checking the number of active Ajax connections by executing the javascript code jQuery.active then depending upon the result we are waiting for the ajax calls to complete until the timeout specified in timeoutInSeconds paameter

Wait for page to load in WebDriver

Unlike Selenium RC(selenium 1) have waitForPageToLoad method to wait until the page to load, WebDriver(selenium 2) doesn't have any method in the API to wait until the page to load. Here is a way to wait until the page elements load properly.
/**
 * Waits for a page to load for timeOutInSeconds number of
 * seconds.
 * 
 * @param timeOutInSeconds
 */
public void waitForPageToLoad(long timeOutInSeconds) {
 ExpectedCondition expectation = new ExpectedCondition() {
  public Boolean apply(WebDriver driver) {
   return ((JavascriptExecutor) driver).executeScript(
     "return document.readyState").equals("complete");
  }
 };
 try {
  log.info("Waiting for page to load...");
  WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
  wait.until(expectation);
 } catch (Throwable error) {
  log.error("Timeout waiting for Page Load Request to complete after "
    + timeOutInSeconds + " seconds");
  Assert.assertFalse(true,
    "Timeout waiting for Page Load Request to complete.");
 }
}
Here we are checking for the "complete" loading state of the web page by JavascriptExecutor and until that we are waiting till the timeout period specified in timeOutInSeconds parameter.

Friday, April 05, 2013

Logging application log to a log file(by File Appender)

To log your application log to a log file by using log4j, you have to go through the following steps:
  1. Download latest jar of log4j.jar and add it to your project classpath.
  2. Create a log4j.properties file inside your source directory to define properties of your logger.
  3. To log your application log to a log file, you need to add the following code in the log4j.properties
  4.  
    #################################################################
    #####     Application Logs to be printed in the log file    #####
    #################################################################
     
    log4j.rootLogger= WARN, FILE_APPENDER
    
    # test appender  daily rolling logs format
    log4j.appender.FILE_APPENDER=org.apache.log4j.DailyRollingFileAppender
    log4j.appender.FILE_APPENDER.File=logs/autoLog.log
    log4j.appender.FILE_APPENDER.DatePattern='.'yyyy-MM-dd
    log4j.appender.FILE_APPENDER.layout=org.apache.log4j.PatternLayout
    log4j.appender.FILE_APPENDER.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p (%F:%M:%L) - %m%n
    
    # test appender  daily rolling logs for packages
    log4j.logger.com.myorg=DEBUG
    log4j.logger.com.myorg.core.util=FILE_APPENDER
    log4j.logger.com.myorg.core.page=FILE_APPENDER
    
  5. To know the usage of logger see the below code:
    //In ConfigUtil.java
    private static Logger log = Logger.getLogger(ConfigUtil.class);
    // The below line is called inside static block
    log.info("Properties file loaded at '" + configLoc + "'");
    
    //In BasePage.java
    protected static Logger log = Logger.getLogger(BasePage.class);
    // The below line is called inside setTimeout() method
    log.info("The timeout value is set to " + timeoutSeconds + " seconds.");
    
    //In DriverManager.java
    private static Logger log = Logger.getLogger(DriverManager.class);
    // The below line is called inside static block
    log.info("Driver location is set to '" + driverLoc + "'");
    
  6. You will get your application log in the log file(which you have specified in your log4j.properties, in this example i have specified "logs/autoLog.log" file) as shown in the below sample:
     
    2013-09-05 12:36:04  INFO (ConfigUtil.java::39) - Properties file loaded at '/Users/aksahu/MySpace/Web_Workspace/KnowledgeBase/config/config.properties'
    2013-09-05 12:36:04  INFO (BasePage.java:setTimeout:155) - The timeout value is set to 60 seconds.
    2013-09-05 12:36:04  INFO (DriverManager.java::54) - Driver location is set to '/Users/aksahu/MySpace/Web_Workspace/CoreDriver/drivers/'
    2013-09-05 12:36:04  INFO (DriverManager.java:getDriver:85) - initializing 'chrome' driver...
    2013-09-05 12:36:15  INFO (BasePage.java:windowMaximize:101) - Maximizing the browser window.
    2013-09-05 12:36:17  INFO (BasePage.java:openUrl:86) - Openning the url 'http://knowledgebase-wiki.appspot.com/' in the browser...
    2013-09-05 12:36:23  INFO (BasePage.java:waitForPageToLoad:956) - Waiting for page to load...
    2013-09-05 12:36:23  INFO (BasePage.java:typeByID:195) - Entering text 'java' to the element specified by id 'searchField'
    2013-09-05 12:36:23  INFO (BasePage.java:clickByID:258) - Clicking on the element specified by id 'resultDiv0'
    2013-09-05 12:36:23  INFO (BasePage.java:waitForElementLocatedByXpath:848) - Waiting for the element specified by xpath '//a[contains(text(),'[Go to page]')]'
    2013-09-05 12:36:23  INFO (BasePage.java:clickByXpath:238) - Clicking on the element specified by xpath '//a[contains(text(),'[Go to page]')]'
    2013-09-05 12:36:24  INFO (BasePage.java:waitForPageToLoad:956) - Waiting for page to load...
    2013-09-05 12:36:24  INFO (BasePage.java:isTextPresent:807) - Checking for the text 'Installing Java' in the page
    2013-09-05 12:36:24  INFO (BasePage.java:isTextPresent:807) - Checking for the text 'java' in the page
    2013-09-05 12:36:24  INFO (BasePage.java:quitBrowser:582) - Closing all the instances of the browser 'chrome'
    

Logging application log in the Console(by Console Appender)

To log your application log in the console by using log4j, you have to go through the following steps:
  1. Download latest jar of log4j.jar and add it to your project classpath.
  2. Create a log4j.properties file inside your source directory to define properties of your logger.
  3. To log your application log in the console, you need to add the following code in the log4j.properties
  4.  
    ################################################################
    #####     Application Logs to be printed in the console    #####
    ################################################################
     
    log4j.rootLogger= WARN, CONSOLE_APPENDER
    
    # console appender format
    log4j.appender.CONSOLE_APPENDER=org.apache.log4j.ConsoleAppender
    log4j.appender.CONSOLE_APPENDER.layout=org.apache.log4j.PatternLayout
    log4j.appender.CONSOLE_APPENDER.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p (%F:%M:%L) - %m%n
    
    # console appender for packages
    log4j.logger.com.myorg=DEBUG
    log4j.logger.com.myorg.core.util=CONSOLE_APPENDER
    log4j.logger.com.myorg.core.page=CONSOLE_APPENDER
    
  5. To know the usage of logger see the below code:
    //In ConfigUtil.java
    private static Logger log = Logger.getLogger(ConfigUtil.class);
    // The below line is called inside static block
    log.info("Properties file loaded at '" + configLoc + "'");
    
    //In BasePage.java
    protected static Logger log = Logger.getLogger(BasePage.class);
    // The below line is called inside setTimeout() method
    log.info("The timeout value is set to " + timeoutSeconds + " seconds.");
    
    //In DriverManager.java
    private static Logger log = Logger.getLogger(DriverManager.class);
    // The below line is called inside static block
    log.info("Driver location is set to '" + driverLoc + "'");
    
  6. You will get your application log as shown in the below example:
     
    [TestNG] Running:
      /private/var/folders/cl/34rlg3ns31g8w4jktmpkc2440000gn/T/testng-eclipse--1656210619/testng-customsuite.xml
    
    2013-09-05 12:58:03  INFO (ConfigUtil.java::39) - Properties file loaded at '/Users/ashwin/MySpace/Web_Workspace/KnowledgeBase/config/config.properties'
    2013-09-05 12:58:03  INFO (BasePage.java:setTimeout:155) - The timeout value is set to 60 seconds.
    2013-09-05 12:58:03  INFO (DriverManager.java::54) - Driver location is set to '/Users/ashwin/MySpace/Web_Workspace/CoreDriver/drivers/'
    2013-09-05 12:58:03  INFO (DriverManager.java:getDriver:85) - initializing 'chrome' driver...
    2013-09-05 12:58:09  INFO (BasePage.java:windowMaximize:101) - Maximizing the browser window.
    2013-09-05 12:58:12  INFO (BasePage.java:openUrl:86) - Openning the url 'http://knowledgebase-wiki.appspot.com/' in the browser...
    2013-09-05 12:58:18  INFO (BasePage.java:waitForPageToLoad:956) - Waiting for page to load...
    2013-09-05 12:58:18  INFO (BasePage.java:typeByID:195) - Entering text 'java' to the element specified by id 'searchField'
    2013-09-05 12:58:19  INFO (BasePage.java:clickByID:258) - Clicking on the element specified by id 'resultDiv0'
    2013-09-05 12:58:19  INFO (BasePage.java:waitForElementLocatedByXpath:848) - Waiting for the element specified by xpath '//a[contains(text(),'[Go to page]')]'
    2013-09-05 12:58:19  INFO (BasePage.java:clickByXpath:238) - Clicking on the element specified by xpath '//a[contains(text(),'[Go to page]')]'
    2013-09-05 12:58:19  INFO (BasePage.java:waitForPageToLoad:956) - Waiting for page to load...
    2013-09-05 12:58:19  INFO (BasePage.java:isTextPresent:807) - Checking for the text 'Installing Java' in the page
    2013-09-05 12:58:19  INFO (BasePage.java:isTextPresent:807) - Checking for the text 'java' in the page
    2013-09-05 12:58:19  INFO (BasePage.java:quitBrowser:582) - Closing all the instances of the browser 'chrome'
    PASSED: testJavaModule
            Verifies the Java Module form Knowledge base
    
    ===============================================
        Default test
        Tests run: 1, Failures: 0, Skips: 0
    ===============================================
    

Tuesday, March 05, 2013

Getting started with WebDriver (Selenium 2)

WebDriver is a automation testing tool for automating testing web applications. It provides tester friendly API which is easy to explore and understand. This tool is not tied to any particular framework such as JUnit or TestNG. It can be used with simple "main" method or any of the unit testing framework such as JUnit or TestNG.

Required downloads: 
  • Download from here the latest version of selenium-server-standalone-x.y.z.jar where x, y and z are digits specifying the version of jar while created by the developers. 
  • Download respective drivers for your browser. Such as FirefoxDriver for Firefox, ChromeDriver for Chrome, InternetExplorerDriver for Internet Explorer and so on.
Quick steps: 
  1. Create a new java project in your favorite IDE 
  2. Add the downloaded jar file into your project build-path. 
  3. Make sure the browser you are selecting to run is installed in your machine.
  4. Copy and paste the following example to execute your first example on WebDriver.
Example Test:

In my example below i have chosen Firefox browser. Here i have not used any framework to execute my test, i have used simple "main" method to execute. The example is self explanatory by its comments.


package com.example.tests;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class GoogleTest {

 public static void main(String[] args) {

  // I have chosen Firefox browser to execute my script
  WebDriver driver = new FirefoxDriver();

  // Go to the Google home page
  driver.get("https://www.google.co.in/");
  
  // Maximize the browser window
  driver.manage().window().maximize();

  // Enter the query string "Cheese"
  WebElement query = driver.findElement(By.name("q"));

  // Type 'aksahu blog' in the search field
  query.sendKeys("aksahu blog");
  driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

  // Click on the 'A. K. Sahu's Blog' link
  WebElement blog = driver.findElement(By.linkText("A. K. Sahu's Blog"));
  blog.click();
  driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

  // Quit the browser
  driver.quit();
 }
}