Config Cucumber and Selenium with Maven on Eclipse

Hello guys,

Today I will post the link for a project on github that contains a basic setup to run your automation on Selenium and Cucumber with Maven on Eclipse.

https://github.com/rafaelaazevedo/cucumber-maven-selenium

Don’t forget to change the path of the chrome driver, features folder and glue package.

The project is on github, so feel free to clone and use as you want. We usually forget about how to do this first configuration as we just need to do in the beginning of the project. Hope this makes you save some time xD

How to create your tests with Protractor and cucumber

Hello guys, today I will post about how to do assertions when using Cucumber and protractor. If you don’t know what is a promise and how they work, I suggest read this link. WebDriver’s JavaScript API is entirely asynchronous and every command results in a promise. WebDriverJS uses a custom promise library with a promise manager called the ControlFlow. The ControlFlow implicitly synchronizes asynchronous actions, making it so you only have to register a promise callback when you want to catch an error or access a return value.

  • So, create a protractor.js in your project’s root folder:
'use strict';

var os = require('os');
var platform = os.platform();

var HOST = 'http://test.protractor.com';
var USER = 'protractor';
var PASS = 'test';

var chrome = {
 browserName: 'chrome'
};

var safari = {
 browserName: 'safari'
};

var firefox = {
 browserName: 'firefox'
};

var capabilities = [chrome];

// Enable Safari only on macos
if (platform === 'darwin') {
 capabilities.push(safari);
}

exports.config = {
 seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
 specs: [
 'src/features/*.feature'
 ],
 multiCapabilities: capabilities,
 noGlobals: true,
 baseUrl: 'http://localhost:5000',
 framework: 'custom',
 frameworkPath: require.resolve('protractor-cucumber-framework'),
 resultJsonOutputFile: 'test-reports/protractor/protractor.json',
 cucumberOpts: {
 require: [
 'src/js/test/common.js',
 'src/js/test/steps/**/*.js'
 ],
 format: 'pretty',
 strict: true,
 tags: [
 '@smoke',
 '~@pending'
 ]
 },
 params: {

 credentials: {
 username: USER,
 password: PASS
 },

 endpoints: {
 authenticate_url: HOST + '/auth'
 }
 },

 //promise to get browserName
 onPrepare: function() {
 var protractor = require('protractor');
 var browser = protractor.browser;
 return browser.getProcessedConfig().then(function(config) {
 browser.browserName = config.capabilities.browserName;
 });
 }
};

 

  • Create your Feature file in: your_project_folder/src/features/login/login.feature
Feature: Login Page


@smoke
 Scenario: Login success
 Given I am on the login page
 When I input valid username and password
 Then I should be redirected to the management page

 

  • Common.js file which will contain the common libraries (You need install them first with npm install command): your_project_folder/src/js/test/common.js
'use strict';

// Configure chai & sinon
global.expect = require('chai')
 .use(require('sinon-chai'))
 .use(require('chai-string'))
 .use(require('chai-as-promised'))
 .use(require('expect-to-be-a-promise'))
 .expect;

global.sinon = require('sinon');

 

  • Create your step definition file in: your_project_folder/src/js/test/steps/login_steps.js
'use strict';

var LoginActions = require('../login_page/login_actions');
var LoginAssertions = require('../login_page/login_assertions');
var protractor = require('protractor');
var browser = protractor.browser;

var LoginPageSteps = function() {

var loginActions = new LoginActions();
var loginAssertions = new LoginAssertions();

this.Given(/^I am on the login page$/, function() {
    loginActions.getPage();
 });

this.When(/^I input valid username and password$/, function() {
    var credentials = browser.params.credentials;
    loginActions.login(credentials.username, credentials.password);
 });

this.Then(/^I should be redirected to the management page$/, function() {
    return loginAssertions.assertManagementPage();
 });

};

module.exports = LoginPageSteps;

 

  • Create your login elements (map repository for login page) file in: your_project_folder/src/js/test/login_page/login_elements.js
'use strict';

var protractor = require('protractor');
var element = protractor.element;
var by = protractor.by;

function LoginStateElements() {
  return {
    url: function() {
    return '/login';
  },
  username: function() {
    return element(by.model('credentials.username'));
  },
  password: function() {
    return element(by.model('credentials.password'));
  },
  submit: function() {
    return element(by.css('[type="submit"]'));
  },
  form: function() {
   return element(by.css('[ng-submit="form("test")"]'));
  }
 };
}

module.exports = LoginStateElements;

 

  • Create your login actions file in: your_project_folder/src/js/test/login_page/login_actions.js
'use strict';

var LoginElements = require('./login_elements');
var protractor = require('protractor');
var browser = protractor.browser;

function LoginStateActions() {

 var loginElements = new LoginElements();

 return {
  getPage: function() {
     browser.get(browser.baseUrl + loginElements.url());
  },
  login: function(username, password) {
     loginElements.username().click();
     loginElements.username().clear();
     loginElements.username().sendKeys(username);
     loginElements.password().click();
     loginElements.password().clear();
     loginElements.password().sendKeys(password);
     loginElements.submit().click();
  }
 };
}

module.exports = LoginStateActions;

 

  • Create your login assertions file in: your_project_folder/src/js/test/login_page/login_assertions.js
'use strict';

var LoginElements = require('./login_elements');

function LoginAssertions() {

 var loginElements = new LoginElements();

 return {
  assertManagementPage: function() {
     var form = loginElements.form();
     var submit = loginElements.submit();
     expect(submit.isEnabled()).to.eventually.be.false;
     return expect(form.isPresent()).to.eventually.be.true;
  }

 };
}

module.exports = LoginAssertions;

 

Chai Assertion Library to understand how to use expect to assert elements.

WebDriver API commands to understand what you can do with the elements, for example, check if is displayed, click, clear, get Title, etc.

 

Thanks To Raphael Bonnet, who has been working with me on this project. It’s great when you find such a good developer to work with and really work as a team trying to find the best for the project together (Even that I am still skeptical about protractor instead of Selenium xD ).

Sending request using a token with node.js

Hey guys, today I will post about how to use a token when sending your requests in node.js. As I am using these requests for my automated tests with cucumber.js, I am going to post the step definition, too.

 

The class with the API requests:

 

'use strict';

var request = require('sync-request');
var protractor = require('protractor');
var browser = protractor.browser;
var sprintf = require('sprintf-js').sprintf;

function API() {

 //Initialise the variables
 var token = null;
 var total = null;
 var id = null;

 return {
  //Authenticate request where it gets the token to be used after
   authenticate: function() {
   var response = request('POST', getAuthURL(), {
   headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
   },
   body: getAuthBody()
 });

 var json = parseResponse(response);
 if (response.statusCode !== 200) {
  throw Error('Unable to authenticate: ' + response.statusCode);
 }

 token = json.token_auth;
 console.log('Authenticated with token:[' + token + ']');

 return token;
 },

 //Get the token from the authenticate request
 create: function() {
  var response = request('GET', getCreateURL(), {
  headers: {
  'Content-Type': 'application/json',
  'Auth-Token': token
  },
  body: getCreateBody()
 });

   var json = parseResponse(response);
   if (response.statusCode !== 200) {
    throw Error('Unable to create:' + response.statusCode);
   }

   //Get the nodes from the response, data is an array
   total = json.total;
   id = json.data[0].id;
   console.log(id);
   console.log('Created:[' + total + ']');

    return json;
   },

   //Parsing the response
   function parseResponse(response) {
    return JSON.parse(response.getBody('utf8'));
   },

   //Returning the body with the credentials from protractor.js config
   function getAuthBody(response) {
    return 'user=' + browser.params.credentials.username +
 '&pass=' + browser.params.credentials.password;
   },

   //Write the body to create the user and convert it
   function getCreateBody(response) {
   return JSON.stringify({
    deviceId: '123456789',
    name: 'Rafaela',
    description: 'Description',
    cities: [{
     'label': 'London'
    }, {
     'label': 'Oxford'
    }]
   });
 },

   //Get address and then endpoint from the protractos.js
   function getAuthURL() {
    return getPath() + '/' + browser.params.endpoints.authenticate;
   },

   //Get the host and path, easier to maintain
   function getPath() {
    return browser.params.host + '/' + browser.params.path;
   },

   function getCreateURL() {
    return getPath() + '/' + browser.params.endpoints.create;
   }

}

module.exports = API;

 

  • Authenticate request where it’s getting the token to be used in the Create request.

 

Your protractor.js with protractor and cucumber configs:

'use strict';

 var os = require('os');
 var platform = os.platform();

 //Browsers that you will run the automation
 var chrome = {
  browserName: 'chrome'
 };

 var safari = {
  browserName: 'safari'
 };

 var firefox = {
  browserName: 'firefox'
 };

 var capabilities = [chrome];

 // Enable Safari only on macos
 if (platform === 'darwin') {
 capabilities.push(safari);
 }

exports.config = {
 seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
 //Point to the features path
 specs: [
 'src/features/*.feature'
 ],
 multiCapabilities: capabilities,
 noGlobals: true,
 baseUrl: 'http://localhost:5000/',
 framework: 'custom',
 frameworkPath: require.resolve('protractor-cucumber-framework'),
 cucumberOpts: {
 //Point to the step definitions and support classes
 require: 'test/steps/**/*.js',
 //Format for the cucumber report
 format: [
 'json:test-reports/cucumber-json/cucumber.json',
 'pretty'
 ],
 strict: true,
 //Tags filtering the scenarios
 tags: [
  '@regressionTests',
  '~@pending'
  ]
 },
 //Params to pass to your tests, username, passwords, etc.
 params: {
  credentials: {
   username: 'user',
   password: 'Password123'
  }
 },
 //Your site address
 host: 'http://www.testSite.com',
 //Path to use in the requests
 path: 'rest',
 //Endpoints for the requests
 endpoints: {
   authenticate: 'auth',
   create: 'create/user'
  }
 }
}
};

 

Your step definition with the step and calling the api functions:

'use strict';

var API = require('../api');

 var SupportSteps = function() {

 var api = new API();

 this.Given(/^I have created the user$/, function() {
       //Calling the authenticate first, you will get the token to use it
       api.authenticate();
       api.create();
     });
 };

module.exports = SupportSteps;

  • So here, you have the step definition that calls the functions to authenticate first and then to create the user after using the token.

Thank you guys ! See you next weekend 🙂

How to post a JSON request in Node.js

Hi guys, today I will post a code snippet to send a post request to the server in Node.js. This could be useful when testing integration between two different websites. For example, when you need to create/update something on a backoffice and you need to check the details on a front-end website.

  • First you need to install this request module with npm:
npm install sync-request

 

  • After you just need to create the js file with the code:
'use strict';

var request = require('sync-request');

var APIMounts = function() {

 var client = {
 id: '123456',
 name: 'Test Client',
 description: 'This client is used for automation',
 age: '20 years',
 city: 'London',
 interests: [{ 'music': 'Rock' }]};

 var details = {
 method: 'POST',
 url: 'http://google.com/rest/client',
 headers: {
 'Content-Type': 'application/json'
 },
 body: JSON.stringify(client)
 };

 function callback(error, response, body) {
 if (!error && response.statusCode === 200) {
 return JSON.parse(body);
 }
 }
 request(details, callback);
};

module.exports = APIMounts;

 

  • client is a variable that will need be formatted
  • interests contains an array of strings with key:value
  • url is the host
  • body is the client variable JSON formatted

 

Resources:

http://blog.modulus.io/node.js-tutorial-how-to-use-request-module

How to set a list of jmeter properties with a list of jmeter variables

Hey guys, today I will post about a quick code to set properties in runtime from jmeter variables.
Where you could use this ?
If you have a list after extract with json path extractor and you want to set a property to use in another thread group, this could be useful.
For example, I will get the serials of a list extracted with json path extractor.
– Create a beanshell script with:
//Get the count of the serials
String countSerials = vars.get("serials_matchNr");

// create a for to create a property for each serial variable
for(int i=1;i<Integer.parseInt(countSerials);i++){

   //set each property + index with the variable of each serial in the list
   ${__setProperty("serials_"+i,String.valueOf(vars.get("serials_"+i)))};

}
Thank you guys ! See you next week 🙂

How to get a random number from a list on Jmeter

Hey folks,

So for today I will post the code I am using on Jmeter to get a random index from a list. So, if you have a json with several ids, for example, and you want to choose one of them to use on the next request, you need:

1 – Create a post processor to get the id node from your json response request. As you may know when you use this plugin, jmeter creates automatically the list of variables with the prefix you have chosen and the suffix “__index”. You can see how to use this plugin on my previous post.

2 – Create a Beanshell Sample

3 – Get a random index from this list of ids or you could use this method to get the random id directly. I found easiest get the index r at least it was the first thing which came into my mind.

import java.util.Random;
String idSize = vars.get("ids_matchNr");
int max = Integer.parseInt(idSize);
int min = 1;
int idx =  min + (int) (Math.random() * ((max - min) + 1));
String id = vars.get("ids_" + Integer.toString(idx));
Thank you guys ! See you next week or before 🙂

Setting Webdriver to run tests in a remote computer

Hey guys,  today I will post about how can you setup your webdriver project to run in a remote machine.

So, first you need set a machine running the selenium server:

java -jar selenium-server-standalone-2.x.x.jar

You will see a message like this:

15:43:07.541 INFO - RemoteWebDriver instances should connect to: 
http://127.0.0.1:4444/wd/hub

 

Then in your code, point webdriver.chrome.driver to the location of chromedriver on the remote machine, like the chrome driver. Also, make sure to start up chromedriver there. If you want to run on your local machine point to: 127.0.0.1:4444/wd/hub

 

 String remoteURL = "http://localhost:9515"; 
 System.setProperty("webdriver.chrome.driver", "/Users/xxxxx/chromedriver");
 WebDriver driver = new RemoteWebDriver(new URL(remoteURL), DesiredCapabi
lities.chrome());
 driver.get("http://www.google.com");
 WebElement element = driver.findElement(By.id("lst-ib"));
 element.sendKeys("Azevedo Rafaela!");
 element.submit();
 driver.quit();

 

Summarising: You have to install a Selenium Server (a Hub), and register your remote WebDriver to it. Then, your client will talk to the Hub which will find a matching webdriver to execute your test.

Hope this helps, a long time that I don’t code using Selenium!

 

Resources:

http://stackoverflow.com/questions/8837875/setting-remote-webdriver-to-run-tests-in-a-remote-computer-using-java

http://stackoverflow.com/questions/9542020/using-selenium-2-remotewebdriver-with-chromedriver

http://selenium-python.readthedocs.org/getting-started.html

https://github.com/SeleniumHQ/selenium/wiki/RemoteWebDriver