Thursday, July 10, 2014

Test Automation: XPATH examples

A common and foremost concern in test automation is to locate or find elements in a page. Using xpath reference is one of the ways to accomplish that. However, many of us are not using xpath properly as we are not aware of its cool features. In fact, most of the times, we approach to xpath only if there is no id or relatively unique class or name are assigned to an element. So xpath is always our last choice. If this is how you feel then you are not using xpath at its full potential. Sometimes I see code like the following:

WebElement wb=driver.findElement(By.xpath(“html/body/div[1]/div[1]/div[2]/form/div/div[2]/div/input”));

This is a not a proper approach to use xpath. Once you do so, your code becomes vulnerable because a simple change in the page may invalidate your element reference.

Here are some cool ways to use xpath. Just google it and you will find lots of tutorials on xpath. But too many examples sometimes can be perplexing. Therefore, you can use the examples I'm going to show here as a starting point to learn xpath. Once you know how to use it you can look for your specific requirement.

1.       Select next element: Let’s start with the basic. Consider the following example:

Suppose you want to locate <body> element here. You can use the following xpath expression:
“/html/body”
Similarly if you want to locate 1st highlighted <div> here, you can use “/html/body/div”.

And for 2nd highlighted <div>, you can use “/html/body/div/div/div[2]”.

We need to notice 3 things here
  • Single slash (/) at the very beginning indicates root element
  • All subsequent slashes select immediately next child element(s)
  • If there are 2 or more child elements, you can specify any of them using index starting from 1.

2.   Relative reference: Now suppose, you have already located the 2nd highlighted <div> in the previous example. So possibly, you have done something like this:

"WebElement wb1=driver.findElement(By.xpath(“/html/body/div/div/div[2]”));"

Now suppose, you want to select the <form> element located under then 2nd <div>. You can simply do the following

WebElement wb2=wb1.findElement(By.xpath(“./form”));

Please note here that as we are trying to find an element relative to another element (wb1), we have user dot (.) in the xpath expression. Dot (.) here indicates the current position of the element.

3.   Select any element: We started looking for an element from the root element in previous two examples. This is not a good practice. Practically, you will want to jump to an element of your concern. For example, in the above example, you could have refer to the body element with the following xpath expression:
//body
Please note, we have used double slash (//) here.  This looks for any appearance of the element of concern.  Suppose, there are 5 input elements in a page.  And they are located in different branches, not necessarily under the same element. You can use the following expression to get all the input elements ignoring their parents or position in the page:
//input
And as you know by now, if you need to select a particular input element, you can use index. For example, //input[2] locates 2nd input element.

So in the example 1, there is only a single form element. Therefore, you don’t have to bother for its position, rather simply use the following expression to locate it:
//form
4.    Select by attribute: Consider the following example:

Suppose you want to locate the highlighted input element. You cannot simply use “//input” as it will return the other input element as well. You can use “//tbody/tr[1]/td[1]/input” but it’s untidy and not recommended. So a better approach is to use attribute to locate element.
If you notice, the names of first and second input elements are different. So let’s pick the "name" attribute here. The expression will look like the following:
//input[@name=’testName’]
Here ‘@’ is used to indicate the attribute of the element <input>. Similarly the expression “//td[@class=’class1’]” locates <td> element with class equals ‘class1’.

User of ‘And’: 
You have to be extra cautions when using attribute to locate element. Make sure the attribute uniquely identifies the element and is not associated with any other unwanted elements. You can use ‘and’ expression if required. For example, you could have used “//input[@name=’testName’ and @class=list]”. This does not add any extra benefit for this example, but you will find this extremely helpful in real life.

5.  Use of ‘contains’: We discussed about how to match attribute in above example. Sometimes you cannot match the entire attribute. Consider the following example:

You want to locate the highlighted <input> element. But its id is auto generated where ‘1231-454-450’ is a dynamic data. So you cannot simply match its id. Here you can use ‘contains’ as shown below
//input[contains(@id,'type')]
It identifies the <input> element having an id that contains the text ‘type’. You can further use ‘and’ to specify it firmly, “//input[contains(@id,'type') and @type='checkbox']”.

6.   Select by text: Sometimes attributes are not good enough to locate an element. You may need to locate it using the text. Consider the following example:

Suppose you want to locate the highlighted <a> element. You can match the text as shown below:
//a[text()='Services We Offer']
Alternately you can write
//a[.='Services We Offer']
Here dot(.) represents the text of the element.

7.   Normalize-space: Consider the previous example. You will often notice that the match does not work properly as the text contains leading or trailing space. So it’s always a better practice to trim space before the match. You can use ‘normalize-space’ in this regard as shown below
//a[normalize-space(text())='Services We Offer']
8.    Any element: Till now we have always specified the element tag. You can use anonymous tag. For example, if you do not want to specify the tagname <a> in previous example then you can write “//*[normalize-space(text())='Services We Offer']”.

Here ‘*’ indicates any element.

9.   Select parent: It’s pretty easy to refer to a parent of current element. Consider the example in item 6. Suppose you want to select the <li> element that contains the highlighted <a> element. You can simply do the following:
//a[text()='Services We Offer']/..
Here, double dot (..) refers to the parent element of the current element.

10. Refer to parent by attribute: one drawback of accessing parent element using double dot is you cannot specify attribute of the parent. Consider the following example:

Here you have a group of checkboxes that share common name. So you can easily locate the checkboxes. Now the requirement is to select a checkbox provided by the text of its parent label.

                                              i.   So first of all you need to get the input elements by name:
//input[@name='services']
This will return all checkboxes sharing common name.

                                            ii.   Then locate their parent element:
//input[@name='services']/parent::label
This will return all <label> element that is parent of the checkboxes.
Here “parent::label” refers to the parent of the current element. And the parent is a label.

                                           iii.  Then match the text:
//input[@name='services']/parent::label[text()='Handicraft']
This will return the label element having the specified text.

                                          iv.    And finally select the checkbox:
//input[@name='services']/parent::label[text()='Handicraft']/input
This will return the specific checkbox.


11.  Following-siblings: This is similar to ‘parent’ above. Sometimes you may need to refer to elements that are not parent or child of another element rather siblings. Consider the following example:

Here you have some <input> element and labels associated with them. But the relationship between the label and input element is not a parent/child relationship. The requirement here is to identify an <input> element by the text of the label associated with it. You can do the following:
//label[text()='First Name']/following-sibling::div/input
Here “following-sibling::div” indicates the next <div> elements that are siblings of the current element.

The reverse of “following-sibling” is “preceding-sibling”.

So these are the xpath techniques I commonly use. Hopefully you will find this helpful. A final suggestion is to install FirePath plugin for firefox. This will help you verify your xpath before you use them in automation script.

Cheers!

Monday, June 16, 2014

Load Testing: Logic Controllers in JMeter (Include, Interleave, Loop, Module, Once Only)


This is a continuation of my previous post (Load Testing: Logic Controllers in JMeter (Transaction, ForEach, If)). Here I show some other useful logic controllers

1.     Include Controller: This helps using same steps across test plans. Suppose you save several test plans and each of them requires you to login to the system. Adding login steps in each test plan is not worthy. Rather you can use include controller as described below.
a.      Create a test plan that contains a Test Fragment and all the steps related to login within it as shown below



c.     Open a different test plan where you want to use this login steps. And add an include controller in place of login steps and provide the file name of the login test plan that you have created in previous steps.


That’s it. Steps from the file as mentioned here will be execute as part of this test plan.

2.    Loop Controller:  As the name suggests, it allows you to loop through steps. Use of it is pretty straight forward. Just add you steps within a loop controller and asks the loop controller how many times it needs to loop through the steps.

  
3.    Interleave Controller: This is not used very often but can be useful sometimes. It allows you to execute alternate steps within a loop. Suppose you have 3 pages that user visits. And you want your test to tool 10 times for these pages. Additionally you want your test to execute only one of those three pages in every loop. You can use Interleave controller in this context as shown below



4.     Module Controller: This allows you to reuse logic controllers within a test plan. Suppose you are visiting a page in your test plan. And it comprises of some HTTP requests, assertions etc. And all these are consolidated with a logic controller. And suppose during the course of load testing you are visiting the same page again within the same test plan. You may not want to repeat the same steps here again. So you can take the help of module controller to refer to that logic controller here. Shows below how you can accomplish that
a.       Get all the steps, you think will repeat, in a single logic controller.
b.    Add a Module Controller to a place where you want the above steps to repeat. And select the logic Controller from ‘Module To Run’ dropdown in module controller.
 
 
5.    Once Only Controller: This, when applied within a loop, executes the associated steps only once across the loops. Suppose, you have a loop and it consists of several steps. You want one of the steps to execute only once when the test is looping across. This is pretty simple. Just add once only controller within the loop and add the steps in it.


Here the steps associated with ‘Transaction Controller: Home Page’ will be executed only once within the loop.

Wednesday, June 11, 2014

Load Testing: Logic Controllers in JMeter (Transaction, ForEach, If)



A simple way to describe JMeter is a tool that captures the way your web application interacts with the web and assesses performance of your web application. Like other testing tools, it has steps that in a combination carry out a particular test. JMeter offers logic controllers to group your steps so that you can ascertain the way the steps behave. One you get along with JMeter, using some of those logic controllers will be inevitable. Here I will try to show how to use some of the logic controllers I often use.

1.    Transaction Controller: This helps you to group steps. Suppose you want to assess the performance of a successful login action. And a successful login action requires more than one HTTP requests. So you can group them in a transaction controller as shown below.


Then add a Summary Report listener to the thread group. Now if you run the test you will notice that a separate assessment is being shown for transaction controller.


2.    ForEach Controller: ForEach controllers are very helpful to loop through an array. Suppose, you are visiting a page that contains a list of some objects. You want to delete some objects with names having a common prefix. And the delete operation requires ID of an object being deleted. Now you can do the followings:
a.    Identify the HTTP request that loads list of the objects. Add a Regular expression extractor (post processors) that extracts IDs of the objects you want to delete. You can configure the extractor as shown below

1.       Give a  name of the variable/array
2.       Enter regular expression that extracts the ID
3.       Add template to refer to group 1 within the regular expression
4.       Add -1 to consider all values returned by the regular expression
5.       Add a default value of the variable

b.      Add ForEach controller and place the delete step within as shown below

1.       Give the reference name of previous step as ‘Input variable prefix’ here
2.       Enter an ‘Output variable name’. This variable will be referred in delete step.
c.       Refer to the ‘Output variable name’ as given above in delete step as shown below

If you run the test now, you will notice that the steps mentioned under ForEach Controller is executed as many times as the IDs the regular expression extractor returns. You can check this in a View Results Tree listener.

3.     If Controller: As the name suggests, it allows you to apply if else condition to your tests. Suppose you have two different sets of steps to create two different types of users. And you want your test to decide which set of steps to execute depending on the value of a variable. You can do the followings
a.    Group the sets of steps as mentioned above in two different If Controllers. And add a ‘User Defined Variables’ config element as shown below

b.    Configure the If Controller  as shown below

Here the Condition asks If Controller to execute the steps only if value of the variable is "Type 1". Similarly you can configure the 2nd If Controller as shown below.


I will show how to use  the following controllers in my next post

  • Include Controller
  • Interleave Controller
  • Loop Controller
  • Module Controller
  • Once Only Controller