Automation with Protractor, PageObject and, Cucumber

Sharing what I did with Protractor

Túlio Bandeira Luz
8 min readJun 13, 2018

I will show how to set up, which practice that I used to run protractor with the beautiful Page Object and Cucumber.

What is Protractor?

Protractor is an end-to-end test framework for Angular and AngularJS applications. Protractor runs tests against your application running in a real browser, interacting with it as a user would.

How does it work?

Protractor is an end-to-end test framework for AngularJS applications. Protractor is a Node.js program that supports the Jasmine and Mocha test frameworks.

Selenium is a browser automation framework. Selenium includes the Selenium Server, the WebDriver APIs, and the WebDriver browser drivers.

Protractor works in conjunction with Selenium to provide an automated test infrastructure that can simulate a user’s interaction with an Angular application running in a browser or mobile device.

Process Communication

The Protractor communication with Selenium Server it is by HTTP, the local server(selenium-server-standalone) or remotely(example: Sauces Labs) send the request by JsonWireProtocol to run interacting in the browser(Chorme, Firefox ou outros).

Why use Protractor?

  • Protractor is built on top of WebDriverJS, which uses native events and browser-specific drivers to interact with your application as a user would;
  • Protractor supports Angular-specific locator strategies, which allows you to test Angular-specific elements without any setup effort on your part;
  • You no longer need to add waits and sleeps to your test. Protractor can automatically execute the next step in your test the moment the webpage finishes pending tasks, so you don’t have to worry about waiting for your test and webpage to sync.

Hands-on

Set up

  • Prerequisite Node.js
  • Install Protractor globally: npm install -g protractor
  • Install the helper that download the browsers and instance of Selenium Server: webdriver-manager update
  • Start the server: webdriver-manager start should be print this log.

Obs.: Remember start the server when you will run the tests.

Tip: Good practice to name files

I like to let the name files with one default in the end like .po to PageObjects and .spec to specifications. This lets more easy to identify my files.

Example:

login.po.js 
login.spec.js

Another example:

loginPage.js 
loginSpec.js

Choose one to use and enjoy. :)

Running the first test

I created the following structure of folders to the first test:

- tests
|- e2e
|- specs
- protractor.conf.js
  • I created a file calls protractor.conf.js, this file will be responsible for my properties of the project.

tests/e2e/protractor.conf.js

exports.config = {
framework: 'jasmine',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['./tests/e2e/specs/*.js']
}

Only this tags on my config file will invoke the default configuration to others tags.

  • I created a file inside my folder specs with name spec.js

tests/e2e/specs/spec.js

1. describe('Protractor Demo App', function() {
2. it('should have a title', function() {
3. browser.get('http://juliemr.github.io/protractor-demo/');

4. expect(browser.getTitle()).toEqual('Super Calculator');
5. });
6. });
  • Line 3 calling the method get(‘http://www.angularjs.org'), the browser will open with the link.
  • Line 4 I’m waiting for the title of the page is (‘Super Calculator’), below is a screenshot about the page
  • To run our test you will run the commands calling the config file(protractor.conf.js), remember to run on terminal inside the folder.
protractor protractor.conf.js
  • Obs.: If your config file calls protractor.conf.js, you just need to run protractor in your terminal to run the tests.

Result:

1 tests, 1 assertion, 0 failures.

Can I use Protractor in application non angular?

When you put the tag below on my protractor.conf.js, I’m telling to run the tests on applications non-angular.

ignoreSynchronization: true,

BUT, using this property, my tests will become delayed, because of that, I must put the waits on my tests.

Tip: “If my application that it is Angular there is a part non-angular, what I need to do”?

Using this tag on my tests to turn on or turn off:

browser.waitForAngularEnabled(false);

Remember to use waits on your tests, because it will be delayed

Page Object

When writing end-to-end tests, a common pattern is to use Page Objects. Page Objects help you write cleaner tests by encapsulating information about the elements on your application page. A Page Object can be reused across multiple tests, and if the template of your application changes, you only need to update the Page Object.

  • Create the following structure of folders to use PageObject:
- tests
|- e2e
|- pages
|- specs.po.js
|- specs
|- spec.spec.js
- protractor.conf.js

Below it is the file structure to use PageObejct.

tests/e2e/pages/spec.po.js

Above it is the specification file to use the Page Object

tests/e2e/specs/spec.spec.js

  • Line 1 spec.spec.js, instancing the PageObject that I will use in my tests.
  • Line 4 spec.spec.js, always that test be will call it will initialize the PageObject.
  • Line 6 spec.spec.js, the test calls the method of getting in PageObject in line 10 of spec.po.js, triggering get(‘http://www.angularjs.org'), the browser it will open in the link.
  • Line 7 spec.spec.js, the test calls the method setName of PageObject spec.po.js to send one parameter a string(‘Julie’), line 14 of spec.po.js the field is filled with received string.
  • Line 9 spec.spec.js, the test expects that the return text on the method specPage.getGreeintText() of spec.po.js, it be equal (‘Hello Julie!’).

Run the test again:

protractor protractor.conf.js
  • Obs.: If your config file calls protractor.conf.js, you just need to run protractor in your terminal to run the tests.

Result:

1 spec, 0 failures

What is Cucumber?

Cucumber is a tool for running automated tests written in plain language. Because they’re written in plain language, they can be read by anyone on your team. Because they can be read by anyone, you can use them to help improve communication, collaboration and trust on your team.

Set up to Cucumber:

How I used a Custom Framework to Protractor, so I must use Chai library, to perform the expects in the tests:

To install:

npm install — save-dev cucumbernpm install — save-dev protractor-cucumber-frameworknpm install chainpm install chai-as-promised
  • I created the following folder structure to cucumber:
- tests
|- e2e
|- features
|- spec.feature
|- pages
|- specs.po.js
|- specs
|- spec.spec.js
- protractor.conf.js

Config file to Cucumber:

protractor.conf.js

  • Lines 06 to 17, I put the preference about the browser, in my case I’m using the Chrome, but There are many options to use.
  • Lines 42 and 43, It’s where I choose the framework that I using on my project, in this case, I’m using Cucumber, the new version of Protractor don’t have it, so I had to informed there is a custom framework if you want you can customize your profile.
  • Lines 45 to 47, this properties is to set up the feature files.
  • Line 54, I put this property with true, at the end of every test, the browser will be restart(It become your tests delayed, I used this tag because, in my scenario I needed, I recommend don’t use this.).
  • Lines 56 to 64, I informed the path to specification files.
  • Lines 93 to 99, onPrepare is the pre-condition that it will be running before the tests, the lines 96 to 99 I declared the cucumber global variables to use on the spec files.

I didn’t need changes on PageObject file.

tests/e2e/pages/spec.po.js

Using cucumber

  • I created the feature file spec.feature.

tests/e2e/features/spec.feature

  • I run the protractor: protractor protractor.conf.js

When I run the Protractor, it showed this log on the terminal.

Resultado:

tests/e2e/specs/spec.spec.js

  • Then I needed to change the spec file, putting all functions inside the file spec.spec.js.

Example:

Given('The user go to {string}', function (string) {
// Write code here that turns the phrase above into concrete actions
return 'pending';
});
  • So, the final spec file using the PageObject must be similar that:
  • Line 1 spec.spec.js, I’m instancing the PageObject that I will use in my tests.
  • Lines 3 to 6 instancing the library of chai, because I used this to assertions on tests.
  • Lines 8 to 10 I put the Before, that’s mean every time the test will run the function init() will initialize the object of PageObject.
  • Line 15 spec.spec.js, I called the function the get(string) of spec.po.js with the parameter a string (URL) received by spec.feature. Line 6 spec.po.js, triggering the function get(string), the browser is open with the link.
  • Line 19 spec.spec.js, I called the function setName(string) of spec.po.js with the parameter a string(name) received by spec.feature.
  • Line 23 to 24 spec.spec.js, I expect that function specPage.getGreeintText() it will return one string and that string it will equal (‘Hello Julie’).

Running the Protractor: protractor protractor.conf.js

  • The test will fail because the string I expect it is “Hello Julie!”, but the getGreeting() returned “Hello Tulio!”, bellow there is an example like the protractor showing the fail.

To this test works I have to change the expect from(‘Hello Julie!’) to (‘Hello Tulio!’).

Thank you so much, guys!!! I hope that you enjoy.

Conclusion

I hope this guide increase your knowledge base, I tried to do something easy and dynamic. I let some tips and good practices in this guide.

I was suffering a problem when I was doing this project, that I’m telling in this post: Protractor — Session ID is null. Using WebDriver after calling quit()?

Feel free to read too.

My repository that I used on this guide.

You can check another structure to use Protractor in this repository:

Reference:

--

--

Túlio Bandeira Luz

I'm a QA Engineer, Computer Player, looking for another way to have fun and blink-182 fan. https://github.com/tuliobluz