QTP – PageObject Design Pattern

by Anshoo Arora on August 29, 2012 | QTP/UFT | 5 Comments

The PageObject design pattern plays the role of modeling areas of UI within test code where methods of PageObjects return other PageObjects. In reality, this concept is similar to the class we saw in the Using Classes as Test Modules where methods return Boolean. This design pattern replaces the Boolean with actual PageObjects which are classes with test code. I wrote about this pattern initially in the context of Selenium (see here) – this article is simply a port to vbs/QTP.

Consider the example below where the Exec method of LoginPage class returns InboxPage.

''Login PageObject
Class LoginPage
    Public Function Exec(ByVal user, ByVal pass)
        'Return InboxPage PageObject
        Set Exec = New InboxPage
    End Function
End Class
 
Dim Login
Set Login = New LoginPage
 
''Inbox PageObject
Class InboxPage
    Public Function GetUnreadMailCount
        'code
    End Function
End Class
 
'Login.Exec(arg, arg) returns the InboxPage PageObject
Set InboxPageObject = Login.Exec("User", "Pass")
 
'The returned object (InboxPage) from the previous statement 
'can be used to execute the method GetUnreadMailCount
iUnreadMails = InboxPageObject.GetUnrealMailCount()

The example above is in its simplest nature. In reality, a single process can return multiple PageObjects. For example, a Login process can return 2 types of page objects: Inbox PageObject (pass) or the Login PageObject (fail).

From the figure above, the Inbox PageObject is returned when the supplied login credentials are valid. In case of invalid login credentials, the process fails and the user is asked to attempt logging into the application again. Because of this behavior, it becomes necessary to build logic for both successful and unsuccessful events.

'Launches the application
Class LaunchApp
    Public Default Function Run()
        'Return Nothing if the initialization fails
        Set Run = Nothing
 
        With Browser("title:=.*Mercury.*")
            If Not .Exist(0) Then
                SystemUtil.Run "iexplore.exe", "http://newtours.demoaut.com"
            End If
 
            If .WebEdit("name:=userName").Exist(10) Then
                'Return the LoginPage PageObject if UserName field is found
                Set Run = New LoginPage
            End If
        End With
    End Function
End Class
 
'Login process
Class LoginPage
    Public Default Function Run(userName, password)
        With Browser("title:=.*Mercury.*")
            .WebEdit("name:=userName").Set userName
            .WebEdit("name:=password").Set password
            .Image("name:=login").Click()
            .Sync
 
            If InStr(.GetROProperty("title"), "Find a Flight") > 0 Then
                'If Welcome page appears = User has logged in
                'Return FindAFlightPage Object
                Set Run = New FindAFlightPage
            Else
                'If the Welcome page failed to appear = Login failed
                'Stay at the Login Page
                Set Run = Me
            End If
        End With
    End Function    
End Class
 
'Contains methods for the Inbox page
Class FindAFlightPage
    'returns SelectAFlightPage
    Public Function GotoSelectFlightsPage()
        'code
    End Function
 
    ' other methods
End Class

The code below shows how the PageObjects above can be used to build tests in QuickTest. Like the 3 classes shown above, the test-code class will also be stored in the function library because by default, classes are private and Actions cannot access classes directly.

The PageObjects created above can be executed the following way:

Set LoginPageObject = (New LaunchApp).Run()
 
Set InboxPageObject = LoginPageObject.Run("test", "test")

Summary

In summary, public methods of the classes in this pattern represent the functionality the page offers. A single class may comprise of multiple public methods which may return 1 or more PageObjects. If it also a good practice to keep the internals of the page as private, to avoid exposing them. Also, a PageObject need not represent an entire page. In practice, it can only represent a section or functionality that may be required to execute several times.

Subscribe to Relevant Codes (by Anshoo Arora)
Hello! We're always posting interesting articles on Relevant Codes.
Why not subscribe so you don't miss out?

Leave a Comment

{ 5 comments… read them below or add one }

Mahesh Upadhyay April 8, 2013 at 1:22 am

Thanks Anshoo, Nice article but need to to knoww if people they have already implemented framework then do you think the PageObject is useful?

Reply

deep September 20, 2012 at 8:18 am

Thanks Anshoo for another great article

Reply

Anonymous August 29, 2012 at 8:33 pm

Great! But I worry about that Maybe LoginPageObject haven’t completed word. I try it,Completed word just can be worked in the test design studio.

Reply

Anshoo Arora September 19, 2012 at 2:34 am

IntelliSense will not be available with QTP 11 and lower. This will change soon when QTP 12 becomes available, or QTP 11.5 – not sure what HP is calling it.

Reply

Dhup Chaya August 29, 2012 at 4:29 pm

Nice one! Thanks, Anshoo.

Reply

Previous post:

Next post: