On this post, I will look at ways of improving Selenium scripts through code refactoring and starting to build a page object model.
DEFINE TEST CASE
I will use again the site of the Vancouver Public Library (http://www.vpl.ca).
The test cases to be automated are related to the login page:
- open the www.vpl.ca site
- click on the MY VPL link
- wait until the next page loads
- click the LOGIN TO MY VPL page
- wait until the next page loads
- login does not work when using an invalid username and invalid pin
- login does not work when using an invalid username and correct pin
- login does not work when using an correct username and invalid pin
- login does not work when using no username and no pin
- login works with correct username and correct pin
The first thing to do is to inspect all HTML elements needed in the script in FIREBUG and identify XPATH expressions for finding them:
MY VPL link
LOGIN TO MY VPL button
//input[@class='field_username text' and @name='name']
//input[@class='text' and @name='user_pin']
As soon as the XPATH expressions are created, I will
- start the Selenium server
- create a new Java project in Eclipse
- add the Selenium Server and Client JARs to the project
- create a new test class
- import the Selenium package to the class
- add the setUp and tearDown methods to the test class for starting and stopping the Selenium server; these methods use the @Before and @After annotations
- create an empty test method
- run the project
- if everything done before is correct, the project should run successfully
It is the time now for adding the code to the test method for the test case:
- the open, click, waitForPageLoad, selenium commands are used for navigating to the Login page
- the type and click selenium commands are used for entering the username and pin values on the Login page
- the click selenium commands is used for submitting the login page
- the getXpathCount selenium command is used for checking if the login failed or succeeded
Run the project again and confirm that there are no errors.
The next step is to copy some of the code for all 5 login page verifications.
The code is identical for the verifications with the exception of the values of the username and pin.
Since some of the verifications need a correct username and pin, I import a new class that provides the correct username and pin values read from an xml file.
Running the project again should not return errors.
The following changes will be done to the code for refactoring:
1. split the test methods in 5 smaller test methods; each verification from the test case is done in a separate test method
2. since each test method takes 14 seconds to run, use @BeforeClass and @AfterClass instead of @Before and @After so that the selenium server is started once before all test methods run and stopped once after all test methods are executed; the test execution time for the methods should go down to 6 seconds because of these changes
3. create a new method for the code that opens the Login page: openPage()
4. create a new method for the code that types the username value:
add a parameter to the method for the username value
5. create a new method for the code that types the pin value: typePin(String pinValue)
add a parameter to the method for the pin value
6. create a new method for the code that submits the login page: submit()
7. create a new method for the code that checks if the login was successful or not: countErrorPopups()
8. replace the code from each test method with the new refactored methods; add the values to the parameter of each method
9. Resolve any errors and run the project
PAGE OBJECT MODEL
Since openPage(), typeUsername(), typePin(), submit() are all things that the Login page does, it makes sense to create a new class called LoginPage and move all refactored methods to it.
By moving the methods to the LoginPage class, the test methods will no longer include any code that shows how the web page works.
The LoginPage class will need a constructor that gets a Selenium parameter so that its methods can call Selenium methods.
After creating the LoginPage class, change the test methods by
- creating a LoginPage object in every test method
- prefix all refactored methods with the name of the LoginPage object
Resolve any errors and run the code.
In this moment, a few things are accomplished:
- Small and independent test methods
- The test methods do not include information about how the site works
- Easy to read and maintain test methods
- I have created a Page Object class for the LoginPage.
All details on how the LoginPage works are in the LoginPage class.
If there are changes in the future for the Login Page, only the Login Page class needs to be modified.
Do you want to learn more about test automation and Java?
I will start an SELENIUM online group training on October 15.
Please see the training details here.