Page Object Manager
In last chapter of Page Object Pattern of Selenium Cucumber Framework, we learned how to design Page Object pattern using Selenium Page Factory in Cucumber. This chapter is again based on Page Objects. But in this chapter we will design a Page Object Manager.
In last chapter we notices that we were creating objects of the different pages using below statement in Cucumber Step Definition files:
HomePage homePage = new HomePage(driver);
ProductListingPage productListingPage = new ProductListingPage(driver);
But what is the problem here. So far we have just one single Cucumber Step Definition file. But in the case of multiple step definition files, we will creating object of Pages again and again. Which is against the coding principle.
To avoid this situation, we can create a Page Object Manager. Duty of the Page Object Manger is to create the page’s object and also to make sure that the same object should not be created again and again. But to use single object for all the step definition files.
Design Page Object Manager Class
1. Create a New Package file and name it as managers, by right click on the src/main/java and select New >> Package. As this Page Object Manager is a part of the framework, we keep this in src/main/java folder.
2. Create a New Class file and name it as PageObjectManager by right click on the above created Package and select New >> Class.
PageObjectManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
package
managers
;
import
org
.
openqa
.
selenium
.
WebDriver
;
import
pageObjects
.
CartPage
;
import
pageObjects
.
CheckoutPage
;
import
pageObjects
.
ConfirmationPage
;
import
pageObjects
.
HomePage
;
import
pageObjects
.
ProductListingPage
;
public
class
PageObjectManager
{
private
WebDriver
driver
;
private
ProductListingPage
productListingPage
;
private
CartPage
cartPage
;
private
HomePage
homePage
;
private
CheckoutPage
checkoutPage
;
private
ConfirmationPage
confirmationPage
;
public
PageObjectManager
(
WebDriver
driver
)
{
this
.
driver
=
driver
;
}
public
HomePage
getHomePage
(
)
{
return
(
homePage
==
null
)
?
homePage
=
new
HomePage
(
driver
)
:
homePage
;
}
public
ProductListingPage
getProductListingPage
(
)
{
return
(
productListingPage
==
null
)
?
productListingPage
=
new
ProductListingPage
(
driver
)
:
productListingPage
;
}
public
CartPage
getCartPage
(
)
{
return
(
cartPage
==
null
)
?
cartPage
=
new
CartPage
(
driver
)
:
cartPage
;
}
public
CheckoutPage
getCheckoutPage
(
)
{
return
(
checkoutPage
==
null
)
?
checkoutPage
=
new
CheckoutPage
(
driver
)
:
checkoutPage
;
}
}
|
Explanation
Constructor
public PageObjectManager(WebDriver driver) {
this.driver = driver;
}
This constructor is asking for parameter of type WebDriver. As to create an object of the Pages, this class requires a driver. Now who so ever will create the object of this class needs to provide the driver like :
PageObjectManager pageObjectManager = new PageObjectManager(driver);
Page Object Creation Method
public HomePage getHomePage() {
return (homePage == null) ? new HomePage(driver) : homePage;
}
This method has two responsibilities:
- To create an Object of Page Class only if the object is null.
- To supply the already created object if it is not null
Modification in Cucumber Step Definition File
The change in above code requires change in our step definition file as well.
Steps.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
package
stepDefinitions
;
import
java
.
util
.
concurrent
.
TimeUnit
;
import
org
.
openqa
.
selenium
.
WebDriver
;
import
org
.
openqa
.
selenium
.
chrome
.
ChromeDriver
;
import
cucumber
.
api
.
java
.
en
.
Given
;
import
cucumber
.
api
.
java
.
en
.
When
;
import
managers
.
PageObjectManager
;
import
pageObjects
.
CartPage
;
import
pageObjects
.
CheckoutPage
;
import
pageObjects
.
HomePage
;
import
pageObjects
.
ProductListingPage
;
public
class
Steps
{
WebDriver
driver
;
HomePage
homePage
;
ProductListingPage
productListingPage
;
CartPage
cartPage
;
CheckoutPage
checkoutPage
;
PageObjectManager
pageObjectManager
;
@Given
(
"^user is on Home Page$"
)
public
void
user_is_on_Home_Page
(
)
{
System
.
setProperty
(
"webdriver.chrome.driver"
,
"C:\\ToolsQA\\Libs\\Drivers\\chromedriver.exe"
)
;
driver
=
new
ChromeDriver
(
)
;
driver
.
manage
(
)
.
window
(
)
.
maximize
(
)
;
driver
.
manage
(
)
.
timeouts
(
)
.
implicitlyWait
(
10
,
TimeUnit
.
SECONDS
)
;
pageObjectManager
=
new
PageObjectManager
(
driver
)
;
homePage
=
pageObjectManager
.
getHomePage
(
)
;
homePage
.
navigateTo_HomePage
(
)
;
}
@When
(
"^he search for \"([^\"]*)\"$"
)
public
void
he_search_for
(
String
product
)
{
homePage
.
perform_Search
(
product
)
;
}
@When
(
"^choose to buy the first item$"
)
public
void
choose_to_buy_the_first_item
(
)
{
productListingPage
=
pageObjectManager
.
getProductListingPage
(
)
;
productListingPage
.
select_Product
(
0
)
;
productListingPage
.
clickOn_AddToCart
(
)
;
}
@When
(
"^moves to checkout from mini cart$"
)
public
void
moves_to_checkout_from_mini_cart
(
)
{
cartPage
=
pageObjectManager
.
getCartPage
(
)
;
cartPage
.
clickOn_Cart
(
)
;
cartPage
.
clickOn_ContinueToCheckout
(
)
;
}
@When
(
"^enter personal details on checkout page$"
)
public
void
enter_personal_details_on_checkout_page
(
)
throws
InterruptedException
{
checkoutPage
=
pageObjectManager
.
getCheckoutPage
(
)
;
checkoutPage
.
fill_PersonalDetails
(
)
;
}
@When
(
"^select same delivery address$"
)
public
void
select_same_delivery_address
(
)
throws
InterruptedException
{
checkoutPage
.
check_ShipToDifferentAddress
(
false
)
;
}
@When
(
"^select payment method as \"([^\"]*)\" payment$"
)
public
void
select_payment_method_as_payment
(
String
arg1
)
{
checkoutPage
.
select_PaymentMethod
(
"CheckPayment"
)
;
}
@When
(
"^place the order$"
)
public
void
place_the_order
(
)
throws
InterruptedException
{
checkoutPage
.
check_TermsAndCondition
(
true
)
;
checkoutPage
.
clickOn_PlaceOrder
(
)
;
driver
.
quit
(
)
;
}
}
|
Notice, now the duty of the creation of all the pages assigned to only one class which is Page Object Manager.
Run the Cucumber Test
Run as JUnit
Now we are all set to run the Cucumber test. Right Click on TestRunner class and Click Run As >> JUnit Test. Cucumber will run the script the same way it runs in Selenium WebDriver and the result will be shown in the left hand side project explorer window in JUnit tab.
Project Explorer
Page Object Classes
Although there are no changes required in our Page Objects classes, but I am pasting all of these for your reference.
HomePage,java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
pageObjects
;
import
org
.
openqa
.
selenium
.
WebDriver
;
import
org
.
openqa
.
selenium
.
support
.
PageFactory
;
public
class
HomePage
{
WebDriver
driver
;
public
HomePage
(
WebDriver
driver
)
{
this
.
driver
=
driver
;
PageFactory
.
initElements
(
driver
,
this
)
;
}
public
void
perform_Search
(
String
search
)
{
driver
.
navigate
(
)
.
to
(
"http://shop.demoqa.com/?s="
+
search
+
"&post_type=product"
)
;
}
public
void
navigateTo_HomePage
(
)
{
driver
.
get
(
"http://www.shop.demoqa.com"
)
;
}
}
|
ProductListingPage.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package
pageObjects
;
import
java
.
util
.
List
;
import
org
.
openqa
.
selenium
.
WebDriver
;
import
org
.
openqa
.
selenium
.
WebElement
;
import
org
.
openqa
.
selenium
.
support
.
FindAll
;
import
org
.
openqa
.
selenium
.
support
.
FindBy
;
import
org
.
openqa
.
selenium
.
support
.
How
;
import
org
.
openqa
.
selenium
.
support
.
PageFactory
;
public
class
ProductListingPage
{
WebDriver
driver
;
public
ProductListingPage
(
WebDriver
driver
)
{
this
.
driver
=
driver
;
PageFactory
.
initElements
(
driver
,
this
)
;
}
@FindBy
(
how
=
How
.
CSS
,
using
=
"button.single_add_to_cart_button"
)
private
WebElement
btn_AddToCart
;
@FindAll
(
@FindBy
(
how
=
How
.
CSS
,
using
=
".noo-product-inner"
)
)
private
List
<WebElement>
prd_List
;
public
void
clickOn_AddToCart
(
)
{
btn_AddToCart
.
click
(
)
;
}
public
void
select_Product
(
int
productNumber
)
{
prd_List
.
get
(
productNumber
)
.
click
(
)
;
}
}
|
CartPage.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package
pageObjects
;
import
org
.
openqa
.
selenium
.
WebDriver
;
import
org
.
openqa
.
selenium
.
WebElement
;
import
org
.
openqa
.
selenium
.
support
.
FindBy
;
import
org
.
openqa
.
selenium
.
support
.
How
;
import
org
.
openqa
.
selenium
.
support
.
PageFactory
;
public
class
CartPage
{
WebDriver
driver
;
public
CartPage
(
WebDriver
driver
)
{
this
.
driver
=
driver
;
PageFactory
.
initElements
(
driver
,
this
)
;
}
@FindBy
(
how
=
How
.
CSS
,
using
=
".cart-button"
)
private
WebElement
btn_Cart
;
@FindBy
(
how
=
How
.
CSS
,
using
=
".checkout-button.alt"
)
private
WebElement
btn_ContinueToCheckout
;
public
void
clickOn_Cart
(
)
{
btn_Cart
.
click
(
)
;
}
public
void
clickOn_ContinueToCheckout
(
)
{
btn_ContinueToCheckout
.
click
(
)
;
try
{
Thread
.
sleep
(
5000
)
;
}
catch
(
InterruptedException
e
)
{
}
}
}
|
CheckoutPage.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
package
pageObjects
;
import
java
.
util
.
List
;
import
org
.
openqa
.
selenium
.
WebDriver
;
import
org
.
openqa
.
selenium
.
WebElement
;
import
org
.
openqa
.
selenium
.
support
.
FindAll
;
import
org
.
openqa
.
selenium
.
support
.
FindBy
;
import
org
.
openqa
.
selenium
.
support
.
How
;
import
org
.
openqa
.
selenium
.
support
.
PageFactory
;
public
class
CheckoutPage
{
WebDriver
driver
;
public
CheckoutPage
(
WebDriver
driver
)
{
this
.
driver
=
driver
;
PageFactory
.
initElements
(
driver
,
this
)
;
}
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_first_name"
)
private
WebElement
txtbx_FirstName
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_last_name"
)
private
WebElement
txtbx_LastName
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_email"
)
private
WebElement
txtbx_Email
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_phone"
)
private
WebElement
txtbx_Phone
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_country_field .select2-arrow"
)
private
WebElement
drpdwn_CountryDropDownArrow
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_state_field .select2-arrow"
)
private
WebElement
drpdwn_CountyDropDownArrow
;
@FindAll
(
@FindBy
(
how
=
How
.
CSS
,
using
=
"#select2-drop ul li"
)
)
private
List
<WebElement>
country_List
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_city"
)
private
WebElement
txtbx_City
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_address_1"
)
private
WebElement
txtbx_Address
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#billing_postcode"
)
private
WebElement
txtbx_PostCode
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#ship-to-different-address-checkbox"
)
private
WebElement
chkbx_ShipToDifferetAddress
;
@FindAll
(
@FindBy
(
how
=
How
.
CSS
,
using
=
"ul.wc_payment_methods li"
)
)
private
List
<WebElement>
paymentMethod_List
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#terms.input-checkbox"
)
private
WebElement
chkbx_AcceptTermsAndCondition
;
@FindBy
(
how
=
How
.
CSS
,
using
=
"#place_order"
)
private
WebElement
btn_PlaceOrder
;
public
void
enter_Name
(
String
name
)
{
txtbx_FirstName
.
sendKeys
(
name
)
;
}
public
void
enter_LastName
(
String
lastName
)
{
txtbx_LastName
.
sendKeys
(
lastName
)
;
}
public
void
enter_Email
(
String
email
)
{
txtbx_Email
.
sendKeys
(
email
)
;
}
public
void
enter_Phone
(
String
phone
)
{
txtbx_Phone
.
sendKeys
(
phone
)
;
}
public
void
enter_City
(
String
city
)
{
txtbx_City
.
sendKeys
(
city
)
;
}
public
void
enter_Address
(
String
address
)
{
txtbx_Address
.
sendKeys
(
address
)
;
}
public
void
enter_PostCode
(
String
postCode
)
{
txtbx_PostCode
.
sendKeys
(
postCode
)
;
}
public
void
check_ShipToDifferentAddress
(
boolean
value
)
{
if
(
!
value
)
chkbx_ShipToDifferetAddress
.
click
(
)
;
try
{
Thread
.
sleep
(
5000
)
;
}
catch
(
InterruptedException
e
)
{
}
}
public
void
select_Country
(
String
countryName
)
{
drpdwn_CountryDropDownArrow
.
click
(
)
;
try
{
Thread
.
sleep
(
2000
)
;
}
catch
(
InterruptedException
e
)
{
}
for
(
WebElement
country
:
country_List
)
{
if
(
country
.
getText
(
)
.
equals
(
countryName
)
)
{
country
.
click
(
)
;
try
{
Thread
.
sleep
(
3000
)
;
}
catch
(
InterruptedException
e
)
{
}
break
;
}
}
}
public
void
select_County
(
String
countyName
)
{
drpdwn_CountyDropDownArrow
.
click
(
)
;
try
{
Thread
.
sleep
(
2000
)
;
}
catch
(
InterruptedException
e
)
{
}
for
(
WebElement
county
:
country_List
)
{
if
(
county
.
getText
(
)
.
equals
(
countyName
)
)
{
county
.
click
(
)
;
try
{
Thread
.
sleep
(
3000
)
;
}
catch
(
InterruptedException
e
)
{
}
break
;
}
}
}
public
void
select_PaymentMethod
(
String
paymentMethod
)
{
if
(
paymentMethod
.
equals
(
"CheckPayment"
)
)
{
paymentMethod_List
.
get
(
0
)
.
click
(
)
;
}
else
if
(
paymentMethod
.
equals
(
"Cash"
)
)
{
paymentMethod_List
.
get
(
1
)
.
click
(
)
;
}
else
{
new
Exception
(
"Payment Method not recognised : "
+
paymentMethod
)
;
}
try
{
Thread
.
sleep
(
3000
)
;
}
catch
(
InterruptedException
e
)
{
}
}
public
void
check_TermsAndCondition
(
boolean
value
)
{
if
(
value
)
chkbx_AcceptTermsAndCondition
.
click
(
)
;
}
public
void
clickOn_PlaceOrder
(
)
{
btn_PlaceOrder
.
submit
(
)
;
}
public
void
fill_PersonalDetails
(
)
{
enter_Name
(
"Aotomation"
)
;
enter_LastName
(
"Test"
)
;
enter_Phone
(
"0000000000"
)
;
select_Country
(
"India"
)
;
enter_City
(
"Delhi"
)
;
enter_Address
(
"Shalimar Bagh"
)
;
enter_PostCode
(
"110088"
)
;
select_County
(
"Delhi"
)
;
}
}
|
Cucumber Test Runner File
No change in Test Runner file.
TestRunner.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package
runners
;
import
org
.
junit
.
runner
.
RunWith
;
import
cucumber
.
api
.
CucumberOptions
;
import
cucumber
.
api
.
junit
.
Cucumber
;
@RunWith
(
Cucumber
.
class
)
@CucumberOptions
(
features
=
"src/test/resources/functionalTests"
,
glue
=
{
"stepDefinitions"
}
)
public
class
TestRunner
{
}
|
Cucumber Feature File
No change in Test Runner file.
End2End_Tests.feature
1
2
3
4
5
6
7
8
9
10
11
12
|
Feature
:
Automated
End2End
Tests
Description
:
The
purpose
of
this
feature
is
to
test
End
2
End
integration
.
Scenario
:
Customer
place
an
order
by
purchasing
an
item
from
search
Given
user
is
on
Home
Page
When
he
search
for
"dress"
And
choose
to
buy
the
first
item
And
moves
to
checkout
from
mini
cart
And
enter
personal
details
on
checkout
page
And
select
same
delivery
address
And
select
payment
method
as
"check"
payment
And
place
the
order
|