How To Write Better Test Automation Code With Test Driven Development

Test automation code can be improved greatly with the Test Driven Development (TDD) principles:
  • don't write a line of new code unless you first have a failing automated test 
  • eliminate duplication





How does test driven development work?


The development process is as follows when TDD principles are applied:
  1. write a test 
  2. make it compile 
  3. make it run 
  4. remove duplication 
  5. continue from 1


These tasks are also called Red/Green/Refactor:

RED - write a little test that doesn't work, perhaps it doesn't even compile

GREEN - make the test work quickly, committing whatever sins necessary in the process

REFACTOR - eliminate all the duplication created in just getting the test to work



How can TDD be used for test automation projects?


The easiest way of seeing TDD in action is through a short automation project.

The following project uses page objects for automating a test case.

The project will be created so that
  • page object classes are created


The test case to automate is quite simple:
  1. open the home page of the Vancouver Public Library site
  2. do a keyword search 
  3. on the results page, check that the number of results is greater than 0



Create the test class template


Lets create the test class template first.

The test class has the following components:

  • empty test script: testBookDetailsDisplayed() 
  • setUp() method for creating the driver object and starting the browser 
  • tearDown() method for closing the driver object and closing the browser

import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;


public class VplTests {

WebDriver driver;

@Before 

public void setUp()
{

System.setProperty("webdriver.chrome.driver", "C:\\Selenium\\BrowserDrivers\\chromedriver.exe");

driver = new ChromeDriver();

}

@After
public void tearDown()
{

driver.quit();

}

@Test
public void testBookDetailsDisplayed()
{

}

}


Executing the code will return the PASS status (green).





Practice RED/GREEN/REFACTOR




Open The Home Page Of The Site


The test script does not do anything yet.

Lets add some code to it.

@Test
public void testBookDetailsDisplayed()
{

HomePage homePage = new HomePage(driver);

assertEquals(homePage.getTitle(), "Vancouver Public Library - Home");

}

The new code lines are needed for the following reasons:
  • create an object (homePage) that corresponds to the HomePage class; the driver object is provided to the HomePage class constructor. 
  • create an assertion to check if the title of the homePage is correct


Running the test script will return the fail status (red).

The test script fails because the HomePage class does not exist.

To go from red to green, I will create the HomePage class and add minimal code to it so that the test script works:

public class HomePage{

public HomePage(WebDriver driver)
{

}

public String getTitle()
{

return "Vancouver Public Library - Home";

}

}

Running the test script will return the pass status (green).


Next, lets do the refactoring phase:

public class HomePage{

WebDriver driver;

String siteUrl = "http://www.vpl.ca";

public HomePage(WebDriver driver)
{
this.driver = driver;
driver.get(siteUrl);
}

public String getTitle()
{

return driver.getTitle();

}

}


Running the test script gets us green status again and we see things happening in the browser.

The updated HomePage class has a few differences compared to its previous version:
  • uses a driver member 
  • stores the driver parameter of the constructor in the driver class member 
  • opens the browser 
  • loads the site in the browser in the constructor using driver.get() 
  • returns the actual title of the page using driver.getTitle()



Do A Keyword Search


Next, lets add the code that does the keyword search.

@Test
public void testBookDetailsDisplayed()
{

HomePage homePage = new HomePage(driver);

assertEquals(homePage.getTitle(), "Vancouver Public Library - HomePage");

ResultsPage resultsPage = homePage.search("java");

assertEquals(resultsPage.getTitle(), "Search | Vancouver Public Library | BiblioCommons");

}

Running the test script fails with a red status.


The search method needs to be added to the HomePage class together with a few other things.

For the search to happen, a few actions are needed:
  • the user clicks in the search text box field
  • the user types the keyword in the search text box
  • the user clicks the search button
  • the results page is loaded  

I will add to the HomePage class 2 members for the locators needed for

  • the search text box
  • search button fields


public class HomePage{

WebDriver driver;

String siteUrl = "www.vpl.ca";

String searchTextBoxLocator = "//input[@id='globalQuery']";

String searchButtonLocator = "//input[@class='search_button']";

public HomePage(WebDriver driver)
{

this.driver = driver;

driver.get(siteUrl);

}

public String getTitle()
{
return driver.getTitle();
}

}



The search method will take a parameter for the keyword value:

public class HomePage{

WebDriver driver;

String siteUrl = "www.vpl.ca";

String searchTextBoxLocator = "//input[@id='globalQuery']";

String searchButtonLocator = "//input[@class='search_button']";

public HomePage(WebDriver driver)
{

this.driver = driver;
driver.get(siteUrl);

}

public String getTitle()
{
return driver.getTitle();
}

public void search(String keyword)
{

WebElement searchTextBox = driver.findElement(By.xpath(searchTextBoxLocator));
searchTextBox.sendKeys(keyword);

WebElement searchButton = driver.findElement(By.xpath(searchButtonLocator));
searchButton.click();

}

}


Running the test script will fail one more time (red).

This time, the failure is caused by the fact that the search method does not return a ResultsPage object.

When using page objects, if the result of a method is that a new page is displayed, the method should return a new page object.


Lets make the change that gets us from red to green:

public class HomePage{

WebDriver driver;

String siteUrl = "www.vpl.ca";

String searchTextBoxLocator = "//input[@id='globalQuery']";

String searchButtonLocator = "//input[@class='search_button']";

public HomePage(WebDriver driver)
{

this.driver = driver;
driver.get(siteUrl);

}

public String getTitle()
{
return driver.getTitle();
}

public ResultsPage search(String keyword)
{

WebElement searchTextBox = driver.findElement(By.xpath(searchTextBoxLocator));
searchTextBox.sendKeys(keyword);

WebElement searchButton = driver.findElement(By.xpath(searchButtonLocator));
searchButton.click();

return new ResultsPage(driver);
}



The change consists in adding the return type of the search method and returning a ResultsPage object.

The driver object is passed to the constructor of the ResultsPage object.

The test script still fails when executed.

We need the ResultsPage class as well:

public class ResultsPage
{

WebDriver driver;

public ResultsPage(WebDriver driver)
{
this.driver = driver;
}

public String getTitle()
{
return driver.getTitle();
}

}

}


We are back to green :)




Check That Results Number Is Greater Than 0

The last part of the script is about checking that the number of results is greater than 0.

I will add the assertion in the test script first:

@Test
public void testBookDetailsDisplayed()
{

HomePage homePage = new HomePage(driver);

assertEquals(homePage.getTitle(), "Vancouver Public Library - HomePage");

ResultsPage resultsPage = homePage.search("java");

assertEquals(resultsPage.getTitle(), "Search | Vancouver Public Library | BiblioCommons");

assertTrue(resultsPage.getResultsCount() > 0);

}


Running this test scripts fails with red status.



Lets go to green fast:

public class ResultsPage
{

WebDriver driver;

public ResultsPage(WebDriver driver)

{
this.driver = driver;
}

public String getTitle()

{
return driver.getTitle();
}

public int getResultsCount()
{
return 10;
}

}


The test script passes now with green status.

Since the getResultsCount() method returns always 10, it needs refactoring:

public class ResultsPage
{

WebDriver driver;

String resultLinkLocator = "//a[@testid='bib_link']";

public ResultsPage(WebDriver driver)
{
this.driver = driver;
}

public String getTitle()
{
return driver.getTitle();
}

public int getResultsCount()
{

List resultsList = driver.findElements(By.xpath(resultLinkLocator));
return resultsList.size();
}

}


The test script and the page object classes are final.

Executing the test script gives us the final green status.


Share this

0 Comment to "How To Write Better Test Automation Code With Test Driven Development"

Post a Comment