Sunday, July 3, 2011

Page Object anyone?

I've heard a lot of discussions lately regarding the implementation of the Page Object design pattern for test teams that are struggling with web applications constantly changing element names and id's. Granted that most of the times developers do a great job at maintaining their element id's uniform throughout the life cycle of the page, however, sometimes such dynamic id's are required by the web site for a range of other reasons. Care to post any? :)

I remember one instance when we implemented page objects for one of our clients, whose goal was not only to alleviate them having to rewrite their failing tests whenever an element id changed on the page, but also to abstract all of the complicated selenium commands from the test developers, freeing them up to concentrate on coding test logic. They had a team of sharp Test Engineers capable of writing Perl code, and named one of them to become the Selenium SME. This subject matter expert would be the one charged with creating the different page objects and exposing methods to interface with the page.

In order to achieve the above goals, we decided on a class for each web site (their company owns numerous websites) that exposes methods to do things like:

  • Signup to the site
  • Login to the site
  • Buy a pay subscription to the site, etc

In addition we also added methods that facilitate numerous tasks that QA engineers perform in their scripts while testing a web site:

  • Check for text on the screen
  • Verify an element is present
  • Check the current page location (url), etc

Below is sample code from one of the methods (check_text) from the first class we created for them. It takes two arguments: the text being sought and the search "mode".

$obj->check_text("find a person", "regexpi");

searches for the text "find a person" anywhere on the page using regular expression mode
Supported modes are:

    regexpi
    glob
    exact

to add more modes just add more cases to the switch statement:


sub check_text {

    my $self = shift;
    my $text = shift;
    my $mode = shift;

    given ($mode) {
        when "regexpi" { $self->{sel}->is_text_present_ok("regexpi:$text");  }
        when "glob" { $self->{sel}->is_text_present_ok("glob:$text"); }
        when "exact" { $self->{sel}->is_text_present_ok("exact:$text"); }
        default { write_log(4, "Search MODE was not supplied\n", $self->{logfile}) }
    }
}

Then, in my script I just instantiate an object, and then use it:


my $text = "some text";

my $obj = PageObj->new();

     if ($text =~ /\*/) {
           $mode = "glob" 
     } else { 
           $mode = "regexpi"; 
     }
     $obj->check_text($text, $mode);

As you can see calling check_text passing in a string is a lot simpler to write than having to know all of the selenium commands required for this. Again, this was important in this organization because they wanted their  test developers to focus on writing code to test functionality and not necessarily have knowledge of the web page under test element id's, names, etc.

2 comments:

  1. Mihir! How are you man! Nice to see you around here. I enjoy your humor on Building C! :)
    See you around cyberspace!

    ReplyDelete

Creative Commons License
VGP-Miami Web and Mobile Automation Blog by Alfred Vega is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.