Wednesday, February 07, 2018

Webdriver io - Part 1

I have been using webdriverio to run selenium ui tests. When I joined the project, i found the code in the following format.
I will provide a brief overview of the improvements I did, to make the code more readable and maintenable.
It could help people who are joining projects with existing code bases and need to continue working on them.

The sample code provided below has been changed so that it is anonymous, but is still useful for instruction purpose.

describe('Loan Application UI', function () {
    var infoTextElement, YellowBtnElement, RedBtnElement, contactElement, landingPageTextElement,

    infoTextElement = 'h3';
    RedBtnElement = 'button:nth-child(3)';
    YellowBtnElement = 'button:nth-child(2)';
    landingPageTextElement = 'h2';
    RedSignInBtnElement = '#LoanApplicationSelected>div>button';
    contactElement = '#BizDetails > div:nth-child(2)';
    userLoginElement = '#UserName';
    passwordElement = '#Password';
    signInBtnElement = '.btn.btn-primary';
    errMsgElement = '#errorMsg'
    errMsgTxt = "We're unable to process your loan application at this time. Please try again.";

    beforeAll(function () {
        browser.timeouts('implicit', 7000);

    beforeEach(() => {

    it('should show the appropriate title for Bank loans Landing Page', function () {
        expect(browser.getTitle()).toBe('Captura Bank loans');

    it('should show the business details when the Captura application is successfully processed', function () {
        expect(browser.getText(contactElement)).toBe('Contact - Tester Captura Account');

     it('should show the expected text for home page', () => {
         expect(browser.getText(landingPageTextElement)).toBe('Bank loans landing page !');

    it('should show the expected information on the landing page', () => {
        expect(browser.getText(infoTextElement)).toBe('Simply select your loan, and follow the steps.');

    it('should have the DownTown Product button selected', () => {
        expect(browser.getText(YellowBtnElement)).toBe('I have Captura DownTown');

    it('should have the HomeBuyer Product button selected', () => {
        expect(browser.getText(RedBtnElement)).toBe('I have Captura Red');

    it('should redirect me to sigin to Red', () => {;;
    it('should show appropriate error msg on error', () => {


The first thing that strikes me when I look at this code is that there are lot of hard coded values in the methods.
Assuming that there are multiple tests,
The second thing is that lower level implementation ( browser.getText) is written at the highest level of the test - which is the page we are looking at now.
So to iterate,
if the password changes from password1 to password2, we have to go to each test manually and change the password.
As a first stage of refactoring, I would be move the value "password1" to a variable and move it to the top of the classs along with the other variables.
In the next stage of refactoring, I would see if this variable is being used by many other test methods ( it should, since login is a common functionality) and I would move it to a different class.
In the third stage, I would identify the common actions ( eg: logging in, selecting a product etc) to an action class.
This would mean that testers who write the automated tests would just need to call the actions appropriate to the flow and the test would be ready to run!

The flow would be something like

 it('should show the user list of bank loans when user has logged in first time', function () {

No comments:

Post a Comment