Please post your Web Driver questions in official Web Driver forum

Tuesday, May 24, 2011

Selenium Tutorial - Verifiying Application Elements

Disclaimer: Objective of this post is to demonstrate how I use Selenium to do soft assertion over collection of element. I don't assert in any way that this is right approach and you are most welcome to prove me  wrong.

So you want to verify collection of elements on you web page. And I assume that you want tests to continue to execute even in the wake of error with some elements. For example you want to test whether text labels for - 'username', 'password' appear on web page. (Though you may like to stop the test execution if 'username', 'password' elements them selves are not there) The worse approach I could think of is to write all assertions in one test, something like -

public void testElements() {
Assert.assertTrue(selenium.isElementPresent("UserNameTextLabel"), 
"Username Text label is not available on page");
Assert.assertTrue(selenium.isElementPresent("PasswordTextLabel"), 
"Password Text label is not available on page");
Some more assertions here
}

Why is this worse approach, it is because any failure with one of the assertion will cause test to be aborted, and you definitely want to continue with test execution even if some text labels don't appear on page.
Now comes another way of doing assertion using Selenium. We can break each assertion in to their individual methods and check for one text label in each method. So you could do some thing like -



public void testUserNameText() {
Assert.assertTrue(selenium.isElementPresent("UserNameTextLabel"), 
"Username Text label is not available on page");
}
public void testPasswordText() {
Assert.assertTrue(selenium.isElementPresent("PasswordTextLabel"), 
"Password Text label is not available on page");

I believe that this is another bad approach because there would be too much of coding involved with this approach. And more code means more maintenance need. Would not it be nice if we could just have one method to test all labels and at the same time not have it cramped with assertions all around. And also be able to execute all the assertions even if a few of them fail.
This is where Soft Assertion comes for our rescue. Have a look at this post which details about how to use soft assertions with Selenium.

I do so by creating a template like following and not hard coding any of the element locator in test itself
Notice that template may also contain check for count of elements.

# Comment is written with ###
# Module format is - ElementName:::ElementIdentifier;CountOfNumberOfElements
# CountofNumberOfElements would be provided only if applicable 

NumberOfBlog:::h3.entry-title;5
PaginationLinks:::ol[class='ycric-pagination-numbers ycric-clrfix']
AuthorBio:::css=p.author-bio

And a file parser which could read it and supply them to verification methods, i.e.

    public Map  getObjectDefinition(String filePath) throws IOException {
        // Verification Element with no verification for XPath count.
        Map objectDefinition = new HashMap();
        
        // get page components.
        InputStream inputStream = PageObjectReader.class.getResourceAsStream(filePath);
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInputStream));
        String line;
        while(((line = bufferedReader.readLine())!=null)) {
            if(!line.startsWith("#") && line.length() > 0) {
                String key = line.split(":::")[0];
                String[] value = line.split(":::")[1].split(";");                
                objectDefinition.put(key, value); 
            }
        }        
        dataInputStream.close();            
        return objectDefinition;        
    } 
 
And here is the verification method -

 public void verifyObjectDefinitions(Map objectDefinitions) {        

        // Check verification elements.
        for (String key:objectDefinitions.keySet()) {            
            // If Element count is to be checked
            if(objectDefinitions.get(key).length == 2) {
                
                int actualElementCount = WebUtils.getCSSCount(objectDefinitions.get(key)[0]);
                int expectedElementCount = Integer.valueOf(objectDefinitions.get(key)[1]);
                
                customVerification.verifyTrue(key, objectDefinitions.get(key)[0], selenium.isElementPresent(objectDefinitions.get(key)[0]), 
                        actualElementCount, expectedElementCount, selenium.getLocation());
            } else {
                customVerification.verifyTrue(key, objectDefinitions.get(key)[0], selenium.isElementPresent(objectDefinitions.get(key)[0]), 
                        selenium.getLocation());                 
            }            
        }
        customVerification.checkForVerificationErrors();
    }

And test would look as -

@Test(groups="UI", alwaysRun=true)
    public void verifyBlogSection() throws InterruptedException, IOException { 
        
        homePage.getBlogsPage().getSecondBlog();
        
        Map firstBlogElements = pageObjectReader.getObjectDefinition("/conf/CricketNewsFirstBlogPageInfoFile.txt");
        pageTestManager.verifyObjectDefinitions(firstBlogElements);
        
        customVerification.checkForVerificationErrors();
        
    }    

Hence we have -
  •  Concise method to check elements on page, instead of having assertions/verifications scattered all over the method
  • Since we are using Selenium - Soft Assertion, test execution would continue even if one or more elements are not found while reporting errors on missing elements in test report
  • We have also externalized app object to external file, hence elements are not hard coded in tests.

So how do you do element verification using Selenium? Any thoughts?

Came across this post on soft assertion today and found it worth sharing -
http://seleniumexamples.com/blog/guide/using-soft-assertions-in-testng/
Fork me on GitHub