Skip to main content

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/

Comments

  1. Several comments:

    1. I don't normally write tests that verify the existence of a bunch of elements on a page. (Maybe I should, but I don't!) I prefer tests that verify the existence of an element (or group of elements) as a *side effect* of some real-world scenario testing. Thus, a negative test in which a valid username with the wrong password are entered, would obviously not pass if the username and password elements were not present. And hopefully, it would fail as elegantly as possible in this case. But the main point of the test would be to see if the site responded appropriately when the user made this error. Verification of the existence of the username and password elements would happen as a side effect. And this "side-effect testing" would happen numerous times with such important fields.

    2. Given the above, the third of your three summary points is of the most interest to me. I'd like to see this scheme used in a test such as I've described. I'm not a Java programmer so am not sure what the best way to handle the locator look-up would be. It seems that every test that needed firstBlogElements would have to first see if it was already defined, and if not, do the call to pageObjectReader.getObjectDefinition. No?

    3. How does this template scheme differ from using a resource file for storing locators, which is something I heard recommended recently?

    4. For people who do want to test that multiple elements are present on a page, I'd suggest improving the code re-use of verifyObjectDefinitions by reducing the five occurrences of "objectDefinitions.get(key)[0]" to one--just stick the result in a var and use the var from thereon.

    ReplyDelete
  2. Hey Mary,

    I would try to answer one by one -

    1. Agree about *side effect testing*, and this is what I think I would do. Two groups of tests "uiTest" and "functionalTest" for login scenario, where group "functionalTest" is dependent on success of group "uiTest". Though side effect testing would also give almost same result but yet I would prefer this approach. If you have heard of TestNG framework in java - it would mark "functionalTest" as skipped and "uiTest" failed

    2. Exactly, that's the whole idea

    3. "template scheme", that's a new word for me, let me see what I can find on this front

    4. Very valid code Review Comment :-). I am leaving my blog post as it is so other readers could see how deficiencies could be over come from the code snippets after reading your comments.

    ReplyDelete
  3. Hi,
    Assertion is not working in my code.
    here is my code:
    @Test
    public void testPeopleFinderPresent() {

    selenium.waitForPageToLoad("20000");

    Assert.assertTrue(selenium.isTextPresent("People Finder1"),"People Finder is not Present on the Page");

    }


    @Test
    public void testClickonLink() {

    selenium.click("link=People Finder");

    }

    now what my objective is:
    If the Link People Finder is present in the page,then only it will click on the link and continue,otherwise it will not continue.
    But here i mentioned the name as "PeopleFiner1",so it must not continue,but still the control is passing on testclickonLink() function. How can this be resolved?

    I want to stop execution after testPeopleFinderPresent(),if PeopleFinder is not found.

    ReplyDelete
  4. The execution continues because operation - "selenium.click("link=People Finder");"
    is happening in a different method and Assertion -
    "Assert.assertTrue(selenium.isTextPresent("People Finder1"),"People Finder is not Present on the Page");"
    is happening in a different method. You should keep both of them in one method and your issue would be solved

    ReplyDelete
  5. well,Tarun,thanks for the reply.
    But my query is:
    We can have two kind of Test Cases-Show-stopper and non-show stopper.
    For show-stopper scenario,if one test step fails then rest of the test steps will also fail.
    for non-show stopper,if one test step fails,then it will be skipped and rest will continue.Am I right?

    Now what I came to know that if we user Assert,then we can achieve first point and if we use verify then we can achieve second point.

    But for that we have to put all test steps in one method,which is a bit hectic,also it suppresses the modularity.
    If I have 10 steps,and if i want that if setp 3 fails then rest will also fail,then i have to keep step 3 to step 10 in one method!!!

    But if i want that even if step 3 fails,rest step will continue,then we have to use verifytrue?

    and one more point:
    here is mu code after modification:

    public void testPeopleFinderPresent() {

    selenium.waitForPageToLoad("20000");

    Assert.assertTrue(selenium.isTextPresent("People Finder1"));
    selenium.click("link=People Finder");

    }

    i have put selenium.click in the same method as of assertion.Though People finder1 is not present,but it is getting getting clicked.

    ReplyDelete
  6. Hi Tarun,would you mind to modify and modularize my code for one time only,if i paste the full code here?
    :-)))
    if i mention the functionality

    ReplyDelete
  7. You are right about this -

    "But if i want that even if step 3 fails,rest step will continue,then we have to use verifytrue?"

    You would have to use verification methods.

    Abhi - if

    Assert.assertTrue(selenium.isTextPresent("People Finder1"));

    fails then next statement would not be executed for sure. Is there a way for me to access your application?

    ReplyDelete
  8. yes tarun,assertion is working fine.I am sorry,it was my mistake.

    Also-
    Could u pls elaborate on verification method?i found one article of you containing custom verification method?can i go for that?


    and also,it will be very helpful if u can re-arrange/re structure my code for one time only,this is a very short one like adding setup code etc.
    actually i tried to add setup code mentioning browser etc,but just in a mess :-P,so left it.


    agian,thanks for all ur patiennce and reply dude!!!i have been able to produce a demo infront of our team,and w/o ur help that was never possbl :-))))

    ReplyDelete
  9. yes tarun,assertion is working fine.I am sorry,it was my mistake.

    Also-
    Could u pls elaborate on verification method?i found one article of you containing custom verification method?can i go for that?


    and also,it will be very helpful if u can re-arrange/re structure my code for one time only,this is a very short one like adding setup code etc.
    actually i tried to add setup code mentioning browser etc,but just in a mess :-P,so left it.


    agian,thanks for all ur patiennce and reply dude!!!i have been able to produce a demo infront of our team,and w/o ur help that was never possbl :-))))

    ReplyDelete
  10. Thanks for kind words Abhishek.
    See now you know to use Selenium as well as Blogspot :P

    Send me your code, I would try to review and modify asap.

    ReplyDelete
  11. And ya, forgot to mention that you can use custom verification method, Let me know if you face any issue with it.

    ReplyDelete
  12. many thanks Tarun.So before pasting my code,allow me to let you know about the functionality.
    _________________________________________________________________________________________________________________________________________________________________

    Test Case:

    In our company portal,there is a link to find people/employee inside the company.The name of the link is "PeopleFinde".
    Now if i click on the link,it goes to another page which asks for :
    FirstName and,
    LastName as Input.

    Now after entering the First and Last Name,there is a button named as "Find" and we need to click on the button.

    After that,the control goes to another page,where the details of the employee is shown including Signum of employee.(Signum is a just a unique identifier like

    employeeid.)

    now what i am trying to do is:

    I have created a data table in excel sheet,which containd ID,FirstName,LastName and Signum.
    Now using @dataprovider,i am retrieving all data.
    then-
    the retrieved firstname and last name is being typed by selenium and clicks on the Find button.In next page it is reading the Signum value from a html(hope u can

    remind how u helped me a lot in finding that using xpath).
    Now i am checking the value with the database value,which is d expected result.

    This overall functioanlity.

    Now for this scenario,i thought of 3 test cases.

    1.Company Home page is launching properly which is "http://internal.com/page/hub_south_east_asia_oceania/index.jsp".

    2.Then I have to check whether "PeopleFinder" button is present or not.
    If not,it will stop,else continue.

    3. Then it will click on the PeopleFinder button and read data from excel and check for Signum.

    here two points:

    a. Suppose there are 3 entries in the table.So even if for first entry,signum does not match,it should contninue for other entries.(Here probably i have to use

    customverify but not sure.)

    b.and after checking one recorde,control will go back to previous page,so that selenium can type name of next record which is working fine.

    This is the overall scenario.
    Now i am confused,which page i should use as setup page? my home page or other page like google.com? i noticed that if i use google.com as home page then two command

    windows are opening in the background while running.How to close the windows please?

    ______________________________
    i am mailing you the code as it crosees 4096 characters.
    is there any option of attachment here?

    ReplyDelete
  13. I saw your code which u mailed me a couple of suggestions -

    1. Yes you would have to us verify method. But I did not see call to checkForVerifircationErrors(), which should be last statement in your tests. If you don't use it then your test method would never fail, even if there were error.

    2. Don't hard code this path as it would work only in you system and not others - "C:\\Users\\ebanabh\\workspace\\PeopleFinder\\src\\Resources\\Data\\data1.xls"
    instead use getResourceAsStream. Google on it, you would find many resources.

    These methods are not used, so remove them -

    @BeforeTest
    public void beforeTest() {
    }

    @AfterTest
    public void afterTest() {
    }


    3. Your setup page should e your company page and not Google, I am not sure of command windows u get, can u provide me more details?

    4. To maximize the window you can us selenium.windowMaxmize, instead of using Robot class.

    Hope this helps you

    ReplyDelete

Post a Comment

No spam only genuine comments :)

Popular posts from this blog

Selenium Tutorial: Pattern Mathing using Selenium

I must confess I have never been admirer of Regular Expression but then there are times you can not escape from it, especially while working on a website which has dynamic contents appeared in static text and you want to validate it. like - "Validate that this text appears and there is 123 here and 456 here" And the test condition is 123 and 456 could be any three digits but number if digits should not be more than three. In a crude way we can at least test this - Assert.assertTrue(selenium.getText("elementLocator").contains("Validate that this text appears and there is")); but what if text goes wrong after "and there is"... what if more than 3 digits appear in text. This is where pattern matching/regular expression comes for our rescue and we can use matches method of String class to achieve same. So the assertion would be - String text = selenium.getText("elementLocator"); Assert.assertTrue(text.matches("Validate

Using chrome console to test xPath and css selectors

Since the advent of selenium there have been many plugin to test xPath / css selectors but you don’t need any of them if you have chrome browser. Using Chrome console you can test both xPath and css selectors. Launch website to be tested in chrome browser and hit F-12 and you would see chrome console opened in lower pane of application - Hit escape key and console would open another pane to write element locators - And now you can start writing xPath or css selectors in chrome console and test them - The syntax for writing css id - $$(“ ”) And hit the enter key. If your expression is right then html snippet of the application element corresponding to the css selector would be displayed - If you mouse over the html snippet in chrome console then it would highlight the corresponding element in application - If you want to clean console of previously written element selectors then just hit ctrl+L keys and chrome console would be empty again. Pro

Return only first or last element from webelements collection

We often come across situation when there are multiple elements on a page and we probably like to exercise only a few of them using selenium webdriver. May be just first and last element. For example on a search result page we may like to click on only first and last link and not all. This is when Iterables API comes handy. (By the way I am assuming that you have already completed watching selenium training videos :)). Once we have collection of web element then we can use Iterables to get only first or last element as following - Consider that we fetch collection of element as - List< WebElement > webElements = getDriver().findElements(By. id ( "htmlID" ));   Now we can get the first web element from this collection as -  WebElement firstElement = Iterables. getFirst (webElements,  getDriver().findElement(By. id ( "defaultElement" )));   Herein second argument -   (getDriver().findElement(By. id ( "defaultElement" )))    in the me