Skip to content
Advertisement

Protractor + Jasmine: Run same test in parallel with different data inputs

Wondering if there is a possibility to have a data driven tests with protractor + jasmine to execute it in parallel.

I have the following: storeList.json – an array with input params to test individual store. We have around 40 stores – records.

[
    {
     "storeId": "Store_ID_1",
     "storeController": "Store_Controller_1"
    },
    {
     "storeId": "Store_ID_2",
     "storeController": "Store_Controller_2"
    }
]

ordering.js – code (protractor) which takes each element from json above and executes it as separate test.

describe('Ordering', function () {

 all(require('../../assets/data/storeList'), (storeData) => {
    it(`Add all items with all modifiers to cart and checkout on ${storeData.storeId}`, async function () {

        let user = await userGenerator.Registered(storeData);
        await shoppingCartActions.fillCart(storeData,user);

        await homePageActions.openCart();

        await shoppingCartActions.validateCartMath();
        await shoppingCartActions.proceedToCheckout();

        await recommendedActions.continueToDeliveryOptions();

        await deliveryAndTipsActions.pickupAnd15PercentTip();
        await deliveryAndTipsActions.validateCartMath();
        await deliveryAndTipsActions.continueToAddressConfirmation();

        await pickupAddressConfirmationActions.continueToPaymentMethod();

        await paymentActions.fillCardData(storeData);

        await paymentActions.pay();
    });
});});

all.js – a snippet to make ordering.js a bit data driven

module.exports = (data, test) => {
const rows = Array.isArray(data) ? data : [data];

rows.forEach((row, index) => {
    test(row, index + 1)
})};

config.js

exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
baseUrl : 'localhost',
restartBrowserBetweenTests: true,

maxSessions: 3,
multiCapabilities: [{
    'browserName': 'chrome'
}, {
    'browserName': 'chrome'
}, {
    'browserName': 'chrome'
}],

specs: ['./testsuite/ordering/*.js'],

allScriptsTimeout: 20000,
framework: 'jasmine2',
jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 600000,
    isVerbose: true,
},

onPrepare: () => {
    global.all = require('./all');
}};

Using this setup I get 3 instances of chrome running each executing ordering.js test with all available data inputs from storeList. So I get 6 tests executed, but in fact I’m willing 2 tests to be executed in parallel.

Another option I have tried is having multiple json for data input, and copies of ordering js, but that seems to be a bad practice.

Could someone point me to right direction having protractor data driven tests executed in parallel.

Advertisement

Answer

You need to know protractor running in parallel against spec files, rather than it blocks cross all spec files. So a solution is to create many spec files for data rows (per row per spec file).

// protractor conf.js

var fs = require('fs');
var util = require('util');
var uuidv1 = require('uuid/v1');

function splitData2Sepc(datarows) {

  datarows.forEach(function(row) {
    let id = uuidv1();
    let dataFilePath = './data/data_'+id + '.json';
    let specFilePath = './specs/spec_parallel_'+id + '.js';

    // read the spec template
    let templatePath = './specs/template_01.js';
    let template = fs.readFileSync(templatePath, 'utf8');

    // generate data file for per row
    fs.writeFileSync(dataFilePath,JSON.stringify(row));

    // generate spec file for per row
    let content = util.format('var row = require("%s");', dataFilePath);

    fs.writeFileSync(specFilePath,[content, template].join('nn'));
  });

}

var datarows = require('./data/all.js');
splitData2Sepc(datarows);

exports.config = {

  capabilities: {
    browserName: 'chrome',
    shardTestFiles: true,
    maxInstances: 3,
  },
  specs: [
      './specs/spec_parallel*.js'
  ]
};

// specs/template_01.js

describe('', function(row){

  it(`Add all items with all modifiers to cart and checkout on ${row.storeId}`, async function () {

    let user = await userGenerator.Registered(row);
    await shoppingCartActions.fillCart(row.user);
    ...
  });

});

// data/all.js

module.exports = [
  {storeId: 1, user: 'user_01', ...},
  {storeId: 2, user: 'user_02', ...},
  ...
];
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement