Four Picks #2

  • In Super-Simple Mutation Testing Dr. James McCaffrey explains a simple and practical way for using Mutation Testing to measure the effectiveness of a set of test cases
  • Coded UI Test and FitNesse shows you how to integrate a widely used acceptance testing framework FitNesse with newly lunched feature Coded UI Test in Microsoft Visual Studio 2010
  • An introduction to Sahi – Sahi is a test automation tool built for testing Web Applications. The Part 1 gives a quick introduction to the tool while Part 2 covers testing web applications developed with ExtJs framework
  • Now something on Watir – Here is Watir Page Helper Gem which provides some useful helper methods when creating Page Objects using Watir-WebDriver

Four Picks #1

I’ll be running this post on a regular interval, sharing with you four best links on testing, test automation and emerging technologies. This is first in the series and hope you like it.

Four Picks #1

  • StarEast 2011 Making Test Automation Work in Agile Projects presentation from Lisa Crispin. This presentation talks about applying whole team approach for test automation in Agile Projects. There is a great wisdom written in these slides.
  • I.M.Testy (a.k.a Bj Rollison) has written interesting post Automation isn’t bad; bad automation is bad!!
  • Spring 2011 issue of Methods and Tools is out with some interesting articles. I particularly liked
    • Automated Acceptance Tests & Requirements Traceability – This article explores an approach for automated acceptance testing of a Java application using Concordian.
    • RSpec Best Practices – RSpec is a widely used tool for BDD in Ruby. Author explains various best practices while using RSpec in BDD/TDD approach.
  • Design Patterns In Python – I came across this interesting online book through a Twitter link. This book explains commonly used design patterns in Python and how these can be used in Test Automation context. Great read!!

Using XPath Axes for locating elements in Selenium

XPath is a very powerful and widely used mechanism in Selenium for locating elements on a Web Page. XPath is used for locating nodes in an XML document and it can also be used for locating HTML elements in XHTML. Selenium supports XPath along with various other locator strategies. XPath in Selenium extends beyond the simple methods of locating by id or name attributes, and opens up all sorts of new possibilities for locating complex & dynamically rendered elements.

Developers not always follow best practices or testability guidelines while building the applications. XPath comes to your help when you don’t have a suitable id or name attribute for the element you wish to locate. You can use XPath to either locate the element in absolute terms or relative to an element that does have an id or name attribute. XPath locators can also be used to specify elements via attributes other than id and name.

Recently a team approached me for solving a locator problem in Selenium. They were testing an e-commerce web application. They had a difficulty in selecting & adding an item to shopping cart. The table listing the items was rendered dynamically using dynamic ids and complex HTML structure. Following figure shows the structure of page:

ShoppingCart
Shopping Cart Page

The textbox to enter the Quantity and image to add item was buried under layer of div elements inside a td element in a table. The ids for these elements were generated dynamically and it was difficult to add an item dynamically from the test script. Here is html code for Quantity textbox:

For Product 1


<input type="text" id="count_670756" value="" maxlength="3" size="3" name="qty">

For Product 2


<input type="text" id="count_670759" value="" maxlength="3" size="3" name="qty">

As you can see in the above code, we cannot rely on id attribute as it changes every time page is refreshed and secondly name of textbox is not unique.

XPath Axes comes to a great help to resolve this problem and develop a generic location strategy. In simple terms XPath Axes helps to locate elements based on element’s relationship with other elements in a document. For more information, there is a nice tutorial available on W3Schools on XPath & XPath Axes.

Coming back to the problem, first we need to find a unique way to identify a Product in the table. There are two columns which contain unique values namely Product & Article column. However Article column contains primary key from the database so it is highly recommended to use this value as basis to locate the product. We can also use Product column otherwise. Following XPath Query will locate the cell containing the specified Article using XPath functions contains() & text():


xpath=//td[contains(text(),'0002')]

Now we need to find the cell which contains the elements. Here we will use following-sibling axis and find the third cell from the current cell. Following query will return the cell containing Quantity & Add to cart image:


xpath=//td[contains(text(),'0002')]/following-sibling::td[3]

In next step we need to get the actual elements which are located inside the layer of div elements. Here we need to use descendent axis to find the child elements in the cell:


xpath=//td[contains(text(),'0002')]/following-sibling::td[3]/descendant::div[2]/input[@name='qty']

xpath=//td[contains(text(),'0002')]/following-sibling::td[3]/descendant::div[3]/input[@name='add']

Following screen-shot shows the Selenium IDE commands to enter the Quantity and click on the Shopping Cart image:

seleide
Selenium IDE

These actions will be used to add multiple items in various test cases. We need to make these actions more generic and remove the hardcoded Article Id. Following example shows the custom command implemented in Selenium User Extension and Selenium IDE:


Selenium.prototype.doAddItemToShoppingCart = function(locator, value){

                this.doType("xpath=//td[contains(text(),'"+locator+"')]/following-sibling::td[3]/descendant::div[2]/input[@name='qty']", value);

                this.doClick("xpath=//td[contains(text(),'"+locator+"')]/following-sibling::td[3]/descendant::div[3]/input[@name='add']");

}

custcommand
Custom Command in Selenium IDE

We can also create reusable function around these actions in following way for Selenium RC in Java:


public void addItemToShoppingCart(String ArticleId, String Qty) throws Exception
	{
		selenium.type("xpath=//td[contains(text(),'" + ArticleId + "')]/following-sibling::td[3]/descendant::div[2]/input[@name='qty']", Qty);
		selenium.click("xpath=//td[contains(text(),'" + ArticleId + "')]/following-sibling::td[3]/descendant::div[3]/input[@name='add']");
	}

However while using XPath we need to consider the fact that these locators are dependent on structure of the page and the layout of the elements. Any changes to the structure or layout will affect the locators and tests will result into failures.

Update:

Sometimes XPath queries may not work well or tests run slow in browsers that do not have good support for XPaths. CSS selectors is a good alternative in such situations. CSS selectors are considerably faster than XPath. Selenium supports CSS 1.0, 2.0 & 3.0. Following code sample describes CSS selectors for locating the elements from above example:


css=td:contains('0002')+td+td+td>div>form>div>input[name='qty']
css=td:contains('0002')+td+td+td>div>form>div>input[name='add']