Cucumber Java post can be found here.
Guest post by Ram Pasala
Cucumber framework is meant for BDD acceptance testing which are basically scenario validations of an application which helps programmers to test and what not to test in plain understandable language(Gherkin).
1 2 3 4 5 |
Scenario: Google Protractor Given I am on google page When I type "protractor" Then I click search button Then I clear search textbox" |
Now let us see how the above scenario could be converted into plain Javascript code which are nothing but Step Definitions:
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 |
/* * spec.js */ var SearchPage = require('../Pages/searchPage'); var chai = require('chai'); var chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); var expect = chai.expect; var search = function () { 'use strict'; var search = new searchPage(); this.Given(/^I am on google page$/, function () { return expect(search.title()).to.eventually.equal('Google'); }); this.When(/^I type "(.*?)"$/, function (text) { return search.searchTextBox(text); }); this.Then(/^I click search button$/, function () { return search.searchButton.click(); }); this.Then(/^I clear search textbox$/, function () { return search.searchTextBox.clear(); } }; |
Writing Step Definitions Efficiently:
1) Use Page Objects : It is the buzzword these days with test automation setup, Page Objects help you write cleaner tests by encapsulating information about the elements on your application page.
1 2 3 4 5 6 7 8 9 10 |
/* * page.js */ var googleSearch = function () { "use strict"; this.searchTextBox = $("input[name='q']"); this.searchButton = $("button[name='btnG']"); }; module.exports = googleSearch; |
2) DRY principle using “Hooks”: They reduce code repetition by allowing us to perform actions at various points in the cucumber test cycle. They are used to prepare and clean the environment “before” and “after” each scenario is executed.
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 |
/* * hooks.js */ module.exports = function() { //maximize browser and pass the url this.before(function(scenario, callback) { browser.manage().window().maximize(); browser.get(url); callback(); }); // Take screenshot if scenario fails this.After(function (scenario, callback) { if (scenario.isFailed()) { browser.takeScreenshot().then(function (base64png) { var decodedImage = new Buffer(base64png, 'base64').toString('binary'); scenario.attach(decodedImage, 'image/png'); callback(); }, function (err) { callback(err); }); } else { callback(); } }); } |
3) Handling Promises : Since cucumber.js is written using node.js, the step definitions are asynchronous. Instead of traditional callbacks we can either return a promise or use the done callback in our step definitions. Otherwise cucumber doesn’t know when our asynchronous actions are complete.
In the above example of spec.js we made sure to return promises in each step definition
1 2 3 4 5 6 7 |
this.When(/^I type "(.*?)"$/, function (text) { return search.searchTextBox(text); }); this.Then(/^I click search button$/, function () { return search.searchButton.click(); }); |
4) BDD Assertions with Chai-As-Promised: Unlike other popular frameworks like Jasmine which have assertions i.e.“expect” that can resolve promises internally, cucumberjs doesn’t have this capability. We have to rely on other libraries .“Chai-As-Promised” fits the bill.
We used the same in our spec.js file , “expect” is used to match a specific condition and “eventually” resolves the returned promise.
1 2 3 4 5 |
this.Given(/^I am on google page$/, function () { return expect(search.title()).to.eventually.equal('Google'); }); |
5) Use Data Tables : This is one of the powerful features cucumber provides to interact with large data.
Scenario: Data Tables
Given I fill the customer details
| name | department |
| john | retail |
| mary | sales |
| ed | science |
1 2 3 4 |
this.Given(/^I fill the customer details$/, function (data, done) { console.log('table data: ', data.hashes()); done(); }); |
Result : It gives an array of objects
1 |
table data: [ { name: ‘john’, department: ‘retail’ }, { name: ‘mary’, department: ‘sales’ },{ name: ‘ed’, department: ‘science’} ] |
6) Organize Feature Files: We need to make sure that features are independent of each other. Scenarios have to be clubbed using tags and put in a common feature file, this way we can write cleaner step definitions and reduce code complexity.
Allure CI reporting Framework : It is a cool open source framework designed to create test execution reports which are crisp and clear.It can be integrated with many test automation frameworks.For detail instructions on how it works, please refer the Allure-CucumberJS official repo
How to setup Jenkins CI and Allure framework
Sample Allure report
Protractor is a powerful nodeJS program for testing end to end test scenarios of a web application and CucumberJS is a widely accepted BDD framework for acceptance testing, when combined together these two goliaths can change the way we see integration and acceptance testing. Allure test report generation framework is turning lot of heads lately, together these frameworks unleash a robust, scalable and reliable e2e testing framework, exciting times ahead for test automation !
Fork on gitHub
protractor-cucumber-allure boilerplate
This is very well explained. I would try to implement this framework.
Do you have any video course for cucumber and protactor framework together?? Course will help for complete flow.
For using Async Each library in cucumber protractor tests, please see the link
http://protractore2e.blogspot.in/2017/02/assertion-using-cucumber-data-table-in.html
Thank you very much..but i hope, you can make video for this course (cucumber and protactor framework)
Nice article, i tried the code but for some reason Screenshot is not captured , can you please help.. same code i have used