Wednesday, 20 November 2013

Explicit Wait vs Implicit Wait – What is best for me?



This article is intended to throw light on the two types of waits supported by Selenium WebDriver – Explicit Wait and Implicit Wait.

What is Explicit Wait

An explicit wait is the code that we write to wait for a certain condition to occur before moving on further in the code. There are some convenience methods available that will help us to write code that will wait only as long as required. WebDriverWait class in association with ExpectedConditions class is one way to achieve it.

Code sample that shows the usage of the above mentioned classes is:






What is Implicit Wait

An ImplicitWait is to tell WebDriver to wait for a certain amount of time when looking for an element and the element is not immediately available.

Code sample that shows the usage of ImplicitWait is:



The default setting in implicitlyWait() is 0.

What is best for me?

Using ExplicitWait is the preferred choice because:

1.   In case of Explicit Wait, the WebDriverWait class will call/ping the ExpectedConditions class every 500 miliseconds whereas in the case of Implicit Wait, the ping time is 1000 miliseconds so the margin of error is less by 500 miliseconds.
2.   Secondly, once set, implicit wait remains set for the lifetime of the webdriver object instance which is not the case with Explicit Wait.


Hope this article helps to understand the concept of waits in Selenium WebDriver. Comments are welcome.

Friday, 19 July 2013

AJAX controls and Selenium Automation


Selenium AJAX


The objective of this article is to briefly discuss the common issues that one may face when trying to automate an AJAX control using Selenium Automation tool. Let us start with the definition of AJAX.
 
What is AJAX?
  1. AJAX is about updating parts of a webpage, without having to reload the entire webpage.
  2. AJAX stands for Asynchronous Javascript and XML. It is a technique for creating fast and dynamic webpages.
  3. AJAX allows webpages to be updated asynchronously by exchanging small amounts of data with the server in the background.
  4. Examples of applications using AJAX are - Google Search, Gmail, Google Maps, YouTube etc.

Scenario
Let us say that we have a webpage that contains a text field and a button. The initial value in the text field is "Old Value". Now as the user clicks the button, some AJAX magic will happen and the value in the text field will be updated from "Old Value" to "New Value" without reloading the webpage.

The question here is how do we go about testing such functionality?

An obvious approach would be:
  1. Open the web page.
  2. Click on the button &
  3. Check for the updated value in the text field.
However if we try to automate this using Selenium, our test case will fail. What is the reason of failure?

What happens is that the asynchronous nature of AJAX means that the result did not reach from the server immediately but our but our Selenium test case checked for the updated result immediately and failed to fetch the new updated value.

How do we rectify such a problem?

The trick here is to wait for the result to come from the server. Selenium WebDriver supports two types of waits:
  1. Explicit Waits &
  2. Implicit Waits

This concludes our basic article.

Thursday, 4 April 2013

JUnit Framework - Basics

This blog discusses the basics of JUnit. Ok, let's start with understanding what a framework is?

What is a framework

A framework is a predefined structure that dictates the structure and flow of control of our program. We create our application on top of a framework.
We can also say that a framework is a large collection of pre-written code, to which we add our code to solve a problem or carry out some functionality. Examples of a framework - JUnit, Java Swings, AWT classes etc.

Having seen what a framework is, we can now define JUnit.

What is JUnit

JUnit is a unit testing framework for Java programming language. It is a member of the unit testing framework family, collectively known as xUnit.

We have just seen that a framework is a predefined structure. As a result to be able to use JUnit in our application / program we have to follow the rules of JUnit. We have to follow its predefined annotations to carry out work.

Annotations in JUnit

List of commonly used annotations are:
1)   @Test
2)   @Ignore
3)   @Before
4)   @After
5)   @BeforeClass
6)   @AfterClass
7)   @RunWith(Suite.class)
8)   @SuiteClasses({,})
9)   @Parameters
10) @RunWith(Parameterized.class)

Let's quickly see what these annotations are and what purpose do they serve:

@Test : This annotation depicts a test case. All the methods that are preceded by this annotation are actually test cases.

@Ignore : As the name suggests, this annotation is used when we want to ignore a particular test case. Example:

@Ignore
@Test
public void testFreeTrialSignup()
{
    //test case code here..
}

Now when you execute the file containing the above test case as a JUnit test, this test case will be skipped.

@Before : Method preceded by this annotation will be called once before executing each test case. So if you have 4 test cases in your java file, the @Before annotation method will execute 4 times.

@After : Just like the @Before annotation, method preceded by @After annotation will be called once after executing each test case.

@BeforeClass : Method preceded by this annotation will be called once before executing all test cases in a java file. So if you have 4 test cases in your java file, the @BeforeClass annotation method will execute only once.

@AfterClass : Method preceded by this annotation will be called once after executing all test cases in a java file. So if you have 4 test cases in your java file, the @AfterClass annotation method will execute only once.


@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class})
Let say in your program, you have 3 java files that contains all the test cases. You can execute each file invidually as a JUnit test. If you wish to execute all your test cases in a single go, you will have to execute them as a part of the test suite with the help of the above two annotations. Sample example:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;


@RunWith(Suite.class)
@SuiteClasses({TestFreeSignUp.class,TestLogin.class,TestNewEvent.class})
public class TestSuite
{

}


@Parameters
@RunWith(Parameterized.class)
The above two annotations are used when ever you want to create parameterized test cases.

Note that the methods preceded by @BeforeClass, @AfterClass & @Parameters must be public and static methods. This is by rule. If you skip any or both the keywords, eclipse will not complain but as you try to run  the test suite, JUnit will throw errors.

Methods preceded by all other annotations listed above must be public methods.

A sweet and simple program that shows the use of some of the annotations listed above is as follows. Copy paste in your eclipse project to see output:

import org.junit.After;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class testJUnitAnnotations
{

@BeforeClass
public static void atTheRateBeforeClassAnnotationMethod()
{
System.out.println("I am @BeforeClass preceded method. I will run only once." +
" Use me to do initializations.");
}

@Before
public void atTheRateBeforeAnnotationMethod()
{
System.out.println("I am @Before preceded method. I will run each time" +
" before a test is executed.");
}

@After
public void atTheRateAfterAnnotationMethod()
{
System.out.println("I am @After preceded method. I will run each time" +
" after a test case completes execution.");
}

@Test
public void atTheRateTestMehtod1()
{
System.out.println("I am @Test preceded method. I am a test case.");
}

@Ignore
@Test
public void atTheRateIgnoredTestMehtod()
{
System.out.println("I am @Test preceded method. I am an ignored test case.");
}

@Test
public void atTheRateTestMehtod2()
{
System.out.println("I am @Test preceded method. I am a test case.");
}

@AfterClass
public static void atTheRateAfterClassAnnotationMethod()
{
System.out.println("I am @AfterClass preceded method. I will run only once." +
" Use me to do initializations.");
}
}


The output of the program is shown below:

This sums up the JUnit basics tutuorial. Comments are welcome.

Thanks :)

Tuesday, 2 April 2013

Why need a data driven framework?

Understanding Data Driven Testing

Data driven testing generally means executing tests by using multiple sets of data which is separate from test cases. Let us try to understand it with the help of an example:

We need to write a test for let say a sign-up page that asks for 3 things:
1) First Name
2) Last Name
3) Password

Let's try to find out some scenario's for the above mentioned situation:

Scenario 1:   First name is blank. Last name and password are provided.

Scenario 2:   First name and password is provided. Last name left blank.
Scenario 3:   First and last name are provided. Password is not provided.

Now there are two routes to achieve the above functionality:

Route 1: We can write individual tests for each of the scenario above.
Route 2: We can write a single test with different test data for each scenario.

Route 2 is preferable as there will be only one test that will deal with all the scenario's. Here is how the test would be written traditionally:

@Test
public void testSignUp()
{
      //Scenario 1
      String firstName = "";
      String lastName = "X";
      String password = "10";
      
      driver.findElement(By.xpath("111")).sendKeys(firstName);
      driver.findElement(By.xpath("222")).sendKeys(lastName);
      driver.findElement(By.xpath("333")).sendKeys(password);

      driver.findElement(By.xpath("login button")).click();

        
      //Scenario 2
      firstName = "A";
      lastName = "";
      password = "10";
      
      driver.findElement(By.xpath("111")).sendKeys(firstName);
      driver.findElement(By.xpath("222")).sendKeys(lastName);
      driver.findElement(By.xpath("333")).sendKeys(password);

      driver.findElement(By.xpath("login button")).click();


      //Scenario 3
      firstName = "A";
      lastName = "X";
      password = "";
      
      driver.findElement(By.xpath("111")).sendKeys(firstName);
      driver.findElement(By.xpath("222")).sendKeys(lastName);
      driver.findElement(By.xpath("333")).sendKeys(password);

      driver.findElement(By.xpath("login button")).click();
}

Few observations from the above code:

1) Values are hard coded which is not advisable. Tightly coupled data.
2) Clearly lots of duplicate code. 
3) There can be more scenarios. What if first name, last name and password, all three are provided or all three are not provided. 

To handle new scenario's more code would need to be added which will further lead to complexity and more duplicate code. Inefficient isn't it?

Clearly the above code cannot be considered to be data driven since the data is tightly coupled. Any change in the test data will result in changing the test case.

There is a need to make this test case generic so that it could execute variety of test data. Clearly we need to take the data out of the test case.

To do that we need to follow data driven automation framework by using JUnit's Parameterized runner functionality.

Please provide comments so that this blog can futher be refined.

Thanks :)

Sunday, 31 March 2013

Advanced captcha automation class

The intent of this blog is to show you an advanced captcha automation class using Selenium RC. So far you must have seen captcha's that only does addition or subtraction. What if in future, multiplication or division captcha's are also introduced. You regression automation script will fail under those circumstances.

This advanced captcha automation class hadles the following operators:

1) Addition (+)
2) Subtration (-)
3) Multiplication (*)
4) Division (/)
5) Modulus (%)

This class is quite easy to understand. Complete code is as follows:


package MyPack;

import java.lang.String;

//This class is responsible for performing the captcha calculations.
public class CalcCaptcha {

int firstWhiteSpaceIndex;
int nextWhiteSpaceIndex; 
int lastWhiteSpaceIndex;

String captchaString;

public CalcCaptcha()
{
firstWhiteSpaceIndex = 0;
nextWhiteSpaceIndex = 0; 
lastWhiteSpaceIndex = 0;
captchaString = "";
}

public CalcCaptcha(String str)
{
captchaString = str;
}

public String CalculateCaptchaResult()
{
firstWhiteSpaceIndex = captchaString.indexOf(" ");

//+1 from firstWhiteSpaceIndex to get operator
//+1 again for white space after operator so +2(1+1)
nextWhiteSpaceIndex = firstWhiteSpaceIndex + 2;
lastWhiteSpaceIndex = captchaString.lastIndexOf(" ");

String leftOperand = captchaString.substring(0, firstWhiteSpaceIndex);
String rightOperand = captchaString.substring((nextWhiteSpaceIndex+1),lastWhiteSpaceIndex);

int leftNumber = Integer.parseInt(leftOperand),
rightNumber    = Integer.parseInt(rightOperand),
result         = 0;

//The operator is always next to first white space, thus +1.
char  operator = captchaString.charAt((firstWhiteSpaceIndex+1));

switch(operator)
{
case '+':
{
result = leftNumber + rightNumber;
break;
}
case '-':
{
//assuming that leftNumber is always greater than rightNumber.
result = leftNumber - rightNumber;
break;
}
case '*':
{
result = leftNumber * rightNumber;
break;
}
case '/':
{
//division by zero exception handled.
result = leftNumber / rightNumber;
break;
}
case '%':
{
result = leftNumber % rightNumber;
break;
}
}
String final_value = String.valueOf(result);
return final_value;
}
}


How to use this class in Selenium RC is shown below:


package MyPack;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;


public class TestCaptcha
{

/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
Selenium selenium = null;
try
{
selenium = new DefaultSelenium("localhost",4444,"firefox","http://timesofindia.indiatimes.com");

selenium.start();
selenium.open("/poll.cms");
selenium.windowMaximize();
selenium.windowFocus();

String str = selenium.getText("//*[@id='mathq2']");

CalcCaptcha obj = new CalcCaptcha(str);
String final_value = obj.CalculateCaptchaResult();

selenium.type("//*[@id='mathuserans2']", final_value);
}
catch(RuntimeException obj)
{
//Catch division by zero exception.
System.out.println("Exception raised is: " + obj);
}
//selenium.close();
//selenium.stop(); // RC Window
}
}

Comments are welcome.
Thanks :)



Automate jsf rich face calendar component in Selenium WebDriver

This blog is about automating the rich face calendar component using Selenium WebDriver. This is quite a useful component and is used where ever date needs to be filled in. Sample calendar component is shown below:


To start automating the above shown calendar component, we should know:-
1) Current date (we will fetch what the current date is)

2) Target date to set (specified by you)

3) Once we know the current and target date, we can calculate whether we need to click the month increment element or the month decrement element, shown above.

4) After we reach the correct month, the only task left is to calculate which day index to select. Day index starts at zero in the sample calendar shown above.

Code written to implement the above 4 points is:

Current Date


/*
* This method will fetch current date and updates currentDay, currentMonth & currentYear variables.
*/
static void GetCurrentDateMonthAndYear()
{
Calendar cal = Calendar.getInstance();

currentDay   = cal.get(Calendar.DAY_OF_MONTH);

//+1 because month values starts from 0. January = 0.
                currentMonth = cal.get(Calendar.MONTH)+1;

currentYear  = cal.get(Calendar.YEAR);
}



Target Date

Sample program uses the target date as:


String dateToSet = "15/07/2013";

/*
*This method will bisect the target date and upadates  targetDay, targetMonth & targetYear variables.
*/
static void GetTargetDateMonthAndYear(String dateString)
{
int firstIndex = dateString.indexOf("/");
int lastIndex = dateString.lastIndexOf("/");
String month = dateString.substring(0, firstIndex);
targetDay = Integer.parseInt(month);
String day = dateString.substring(firstIndex+1, lastIndex);
targetMonth = Integer.parseInt(day);
String year = dateString.substring(lastIndex+1, dateString.length());
}




Calculate whether we need to click the month increment element or the month decrement object:


/*
* This method decides how many time this ">" element on the calendar component needs to be clicked to reach target month.
*/
static void CalculateHowManyMonthsToJump()
{
if((targetMonth - currentMonth) > 0 )
{
jumpMonthsBy = (targetMonth - currentMonth);
}
else
{
jumpMonthsBy = (currentMonth - targetMonth);
increment = false;
}
}



After we reach the correct month, the only task left is to calculate which day index to select. Day index starts at zero in the sample calendar shown above.


/*
* This calculates the current index that holds the targetDay value that we need to click in the calendar control.
*/
static void CalculateCorrectDayIndex(WebDriver driver)
{
int tempMonth = targetMonth - 1;
if(tempMonth == 0)
{
//if target month is January, control will come inside.
tempMonth = DECEMBER;
}

WebElement element = driver.findElement(By.xpath(dayZeroxPath));
String str = element.getText();
int dayValueAtZeroIndex = Integer.parseInt(str);

if(dayValueAtZeroIndex == 1)
{
index = targetDay - 1;
}
else
{
switch(tempMonth)
{
case JANUARY:
case MARCH:
case MAY:
case JULY:
case AUGUST:
case OCTOBER:
case DECEMBER:
{
index = ((MAX_DAY_IN_A_MONTH - dayValueAtZeroIndex) + targetDay);
break;
}
case FEBRUARY:
{
/*
* Separate case is needed for feb because Feb contains only 28(MAX_DAY_IN_A_MONTH - 3) days.
*/
index = (((MAX_DAY_IN_A_MONTH - 3) - dayValueAtZeroIndex) + targetDay);
break;
}
default:
{
//Control will come here for months that consists of 30(MAX_DAY_IN_A_MONTH - 1) days.

index = (((MAX_DAY_IN_A_MONTH - 1) - dayValueAtZeroIndex) + targetDay);
break;
}
}
}
}
}//end of class.





COMPLETE PROGRAM CODE :

import java.util.Calendar;
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;

interface Xpaths
{
/*
* This inteface contains all the xpath's that are used in the program
*/
String calendarPopUpButtonxPath = "//*[@id='j_id354:j_id355PopupButton']";
String monthIncrementerxPath = "//*[@id='j_id354:j_id355Header']/table/tbody/tr/td[4]/div";
String monthDecrementerxPath = "//*[@id='j_id354:j_id355Header']/table/tbody/tr/td[2]/div";
String dayxPathPart1 = "//*[@id='j_id354:j_id355DayCell";
String dayxPathPart2 = "']";
String dayZeroxPath = "//*[@id='j_id354:j_id355DayCell0']";
String applyButtonxPath = "//*[@id='j_id354:j_id355Footer']/table/tbody/tr/td[6]/div";
}

interface Months
{
int JANUARY   = 1,
FEBRUARY  = 2,
MARCH     = 3,
APRIL     = 4,
MAY       = 5,
JUNE      = 6,
JULY      = 7,
AUGUST    = 8,
SEPTEMBER = 9,
OCTOBER   = 10,
NOVEMBER  = 11,
DECEMBER  = 12;
int MAX_DAY_IN_A_MONTH = 31;
}

public class AutomateJsfCalendar implements Xpaths,Months
{
/**Months
* @param args
*/
static int targetDay     = 0,
          targetMonth   = 0,
          targetYear    = 0;
static int currentDay    = 0,
  currentMonth  = 0,
      currentYear   = 0;
static int jumpMonthsBy  = 0,
  index         = 0;

static boolean increment = true;
public static void main(String[] args)
{
WebDriver driver = new FirefoxDriver();
driver.navigate().to("http://livedemo.exadel.com/richfaces-demo/richfaces/calendar.jsf");
driver.manage().timeouts().implicitlyWait(15L, TimeUnit.SECONDS);
driver.manage().window().maximize();
WebElement element = driver.findElement(By.xpath(calendarPopUpButtonxPath));
element.click();
//At this point, jsf calendar component is displayed.
//Today's date is 30/03/2013. Let us say we want to set the date as 15/07/2013
String dateToSet = "15/07/2013";

GetTargetDateMonthAndYear(dateToSet);
GetCurrentDateMonthAndYear();
CalculateHowManyMonthsToJump();
for(int i=0;i<jumpMonthsBy;i++)
{
if(increment)
element = driver.findElement(By.xpath(monthIncrementerxPath));
else
element = driver.findElement(By.xpath(monthDecrementerxPath));
element.click();
try
{
//sleep will let you see the automation happening.
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
CalculateCorrectDayIndex(driver);
String completePath = dayxPathPart1 + index + dayxPathPart2; 

element = driver.findElement(By.xpath(completePath));
element.click();
element = driver.findElement(By.xpath(applyButtonxPath));
element.click();

  //driver.quit();
}//end of main..
/*
*This method will bisect the target date and upadates  targetDay, targetMonth & targetYear variables.
*/
static void GetTargetDateMonthAndYear(String dateString)
{
int firstIndex = dateString.indexOf("/");
int lastIndex = dateString.lastIndexOf("/");
String month = dateString.substring(0, firstIndex);
targetDay = Integer.parseInt(month);
String day = dateString.substring(firstIndex+1, lastIndex);
targetMonth = Integer.parseInt(day);
String year = dateString.substring(lastIndex+1, dateString.length());
}
/*
* This method will fetch current date and updates currentDay, currentMonth & currentYear variables.
*/
static void GetCurrentDateMonthAndYear()
{
Calendar cal = Calendar.getInstance();
currentDay   = cal.get(Calendar.DAY_OF_MONTH);
currentMonth = cal.get(Calendar.MONTH)+1;//+1 because month values starts from 0. January = 0.
currentYear  = cal.get(Calendar.YEAR);
}
/*
* This method decides how many time this ">" element on the calendar component needs to be clicked to reach target month.
*/
static void CalculateHowManyMonthsToJump()
{
if((targetMonth - currentMonth) > 0 )
{
jumpMonthsBy = (targetMonth - currentMonth);
}
else
{
jumpMonthsBy = (currentMonth - targetMonth);
increment = false;
}
}

/*
* This calculates the current index that holds the targetDay value that we need to click in the calendar control.
*/
static void CalculateCorrectDayIndex(WebDriver driver)
{
int tempMonth = targetMonth - 1;
if(tempMonth == 0)
{
//if target month is January, control will come inside.
tempMonth = DECEMBER;
}
WebElement element = driver.findElement(By.xpath(dayZeroxPath));
String str = element.getText();
int dayValueAtZeroIndex = Integer.parseInt(str);

if(dayValueAtZeroIndex == 1)
{
index = targetDay - 1;
}
else
{
switch(tempMonth)
{
case JANUARY:
case MARCH:
case MAY:
case JULY:
case AUGUST:
case OCTOBER:
case DECEMBER:
{
index = ((MAX_DAY_IN_A_MONTH - dayValueAtZeroIndex) + targetDay);
break;
}
case FEBRUARY:
{
/*
* Separate case is needed for feb because Feb contains only 28(MAX_DAY_IN_A_MONTH - 3) days.
*/
index = (((MAX_DAY_IN_A_MONTH - 3) - dayValueAtZeroIndex) + targetDay);
break;
}
default:
{
//Control will come here for months that consists of 30(MAX_DAY_IN_A_MONTH - 1) days.
index = (((MAX_DAY_IN_A_MONTH - 1) - dayValueAtZeroIndex) + targetDay);
break;
}
}
}
}
}//end of class.

Simply copy paste, the above code in a java source file having the same name as the class name & run to see the calendar component automation.

In addition to the calendar automation, this article shows:

1) Interface that only contain variables.
2) How the class implements multiple interfaces using the <implements> keyword.
3) How to use switch statements.
4) Modular programming by implementing separate method for different tasks.

 Comments are welcome.
Thanks :)