Showing posts with label selenium. Show all posts
Showing posts with label selenium. Show all posts

Tuesday, September 17, 2013

Get Table Data

One of the most common tasks in our project is to retrieve data from a table in order to assert. With this post I will try to describe a unified way to get the required data from any table with a specific format so my assertions are well defined.
The assertion points to be well defined I usually prefer to have my actual data in the form of a Map(key,value) so my assertions are in the form
Assert.assertEquals(data.get(key),expected_value)
I selected the key value for my map to be the value of the first column with value a second map containing as keys the names of the columns and values the values of the columns.
Map(column_n_value:Map(column_2_name:column_2_value,…,column_n_name:column_n_value))
The aforementioned implementation for the key value pairs where chosen to be the table values instead of the table indexes for maintainability purposes. Maintainability wise a column addition or an non shorted table the index will return the wrong result while the value not.
The resulting assertions look like:
Assert.assertEquals(data.get(row_1_value).get(column_2_name),expected_value)
Assert.assertEquals(data.get(row_1_value).get(column_3_name),expected_value)
The first thing we need to do in order to construct our map is to get the number of rows and columns of the table as follows:
rows = selenium.getCssCount("css=table tbody tr").intValue()
columns = selenium.getCssCount("css=table tbody tr td").intValue()
With the number of rows and columns at hand the next step is to retrieve the names of the columns from the table header as follows in groovy:
public List<String> getTableColumnNames(){  
   def headerNames=[]  
   (1..selenium.getCssCount("css=table thead tr th").intValue()).each{columns->  
    if(!selenium.getText("css=table thead tr th" + ":nth-child(" + columns + ")").isEmpty()){  
      headerNames << selenium.getText("css=table thead tr th" + ":nth-child(" + columns + ")")  
    }
   return headerNames
}
Having the column names the next step is to construct the desired map as follows in groovy:
public HashMap<String, HashMap<String, String>> getTableInfo() {  
   selenium.waitForElement(componentName);  
   def TableMap=[:]    
   def columnNames = getTableColumnNames()  
   (1..selenium.getCssCount("css=table tbody tr").intValue()).each{row->  
     def columnMap=[:]
     (2..selenium.getCssCount("css=table tbody tr td").intValue()).each{column->  
      columnMap.put(columnNames[column-1],controller().getText(componentName + ":nth-child("+row+") *:nth-child("+column+")"))  
    }  
    TableMap.put(controller().getText(componentName + ":nth-child(" + row + ") td:nth-child(1)"),columnMap)  
   }  
   return TableMap;  
 }
The above implementation can be found embedded in Stevia, enriched with code detecting your locator style (Xpath, Css or Id).

The above implementation of the table scan could be altered to accept only td as columns by altering the column map to get
td:nth-child("+column+")
instead of
*nth-child("+column+")
Stevia includes similar methods such as: 
  • getTableInfoAsList 
  • getTableElements2DArray
  • getTableElementTextUnderHeader
Read More

Wednesday, July 3, 2013

Many applications allow or require a user, to perform multiple or complicated actions, like drag and drop.
In this post we will describe how we can implement, such actions with the use of  SeleniumRC and the Web Driver.

Selenium RC
In the Selenium RC case, a user can perform all the actions upon a selenium instance.
All user interactions are performed sequentially. Some examples are the following:
selenium.dragAndDropToObject(locatorFrom, locatorTo);
selenium.keyDownNative (thekey.getEvent());

Web Driver
In Web Driver, things are a little more complicating, thus interesting. First of all we will introduce class Actions of the selenium (package org.openqa.selenium.interactions).
The Actions class is user-facing API for emulating complex user gestures. Web Driver users can use this class to simulate usage of keyboard or mouse events.
The Actions class contains the keyboard and mouse related actions. For example:
 click(WebElement onElement)  
 clickAndHold(WebElement onElement)
doubleClick()  
 doubleClick(WebElement onElement)
dragAndDropBy(WebElement source, int xOffset,int yOffset) 
 keyDown(Keys theKey) 
 keyDown(WebElement element, Keys theKey)
keyUp(Keys theKey)
keyUp(WebElement element, Keys theKey)
moveByOffset(int xOffset, int yOffset)
In order to use the above mentioned actions the user should do the following
First of all, the user must create an instance Actions class
Actions builder = new Actions(driver);
where driver is a Web Driver instance.

Let us explain all the above, a little...
In the Actions class, the user, can perform one action, by simply calling it into the driver instance, followed by the method perform().
For example, if I wanted to double click somewhere:
Actions builder = new Actions(driver);
driver.doubleclick().perform();
This is ok, in the case that the user wants to perform only one action at a time.
But what happens when a user wants to perform many actions? The obvious way to do it, is to perform these actions sequentially. This is made easier, by the fact that all Actions methods return an Actions object.
builder.clickAndHold(ElementA)
       .moveToElement(ElementB)
       .release(ElementA)
       .keyUp(Keys.CONTROL).perform();
A smoother and cooler way to do the above, would be to wrap all these actions in one method, and just call it.
This can be done with the use of the interface Action. The Action interface only has one action - perform().
Action dropAToB= builder.build();
dropAToB.perform();
 In the above example, we dragged ElementA and dropped it to ElementB, using multiple actions.
As a conclusion, Web Driver wins on points Selenium RC, in terms of simplicity. A selenium user will have to execute all actions separately, and sequentially, whereas, a Web Driver user, will just create an actions-chain, upon the driver instance, and execute all the actions in one line.
Read More

Thursday, April 4, 2013

Stevia is coming ...

Back in 2011 while implementing the page object maintainability technique in our test code the idea of creating a framework for testing web apps using java and selenium was created. Couple of years later and after some back and forth the framework became to realization and the name of it is: STEVIA.

Stevia is a Java-based framework created by the encapsulation of three major technologies
·         TestNG (a well-known unit testing framework)
·         Selenium (a well-known framework for automation of user actions via browsers)
·         Spring (the most commonplace user library in Java).

While the release of Stevia is imminent to Github  and in the open source community, a first release of our technical document is uploaded in the following link: http://goo.gl/Is3lA for user reactions gathering. Please have a good read through and/or comment if you think more details are needed.

The document will stay for a week uploaded for everyone who wishes to comment and all constructive reviews are more than welcome. For any technical inquiries and details of the release, feel free to ping as at stevia-release [at] persado.com

Stay tuned for the upcoming release early next week.

UPDATE: We have released it! Check here and on GitHub!
Read More