From dfdc1d412f8e8633cb3d628b22c62a4a6f217c60 Mon Sep 17 00:00:00 2001 From: Kushang Gajjar Date: Mon, 19 Jun 2017 14:46:21 -0400 Subject: [PATCH] Support for Cucumber v2 (#15) * Cucumber V2 has released with bunch of changes. Updating this module to support Cucummber-V2. * support Cucumber-2 * test with Node 7 * add tests for mapping scenarios per feature * fix for parallel.scenarios * add changelog * readMe * highlight * readme --- .gitignore | 2 + .travis.yml | 2 +- CHANGELOG.md | 7 + README.md | 72 +- lib/cucumber/cucumber_js.js | 158 +++-- lib/parallelizer/parallelizer.js | 28 +- lib/parallelizer/reporter.js | 54 +- lib/tasker/parser.js | 2 +- lib/tasker/tasks.js | 8 +- package.json | 26 +- test/config/config.json | 3 + test/features/assert/assertReport.js | 2 +- test/features/assert/report.js | 14 +- test/features/parallel_1.feature | 6 +- test/features/parallel_2.feature | 6 +- .../step_definitions/parallelStepDefs.js | 34 +- test/report/.gitignore | 1 + test/report/cucumber_report.json | 658 ------------------ test/report/generateReport.js | 9 + 19 files changed, 272 insertions(+), 820 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 test/report/.gitignore delete mode 100644 test/report/cucumber_report.json create mode 100644 test/report/generateReport.js diff --git a/.gitignore b/.gitignore index 9f0fdca..e669f7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /.idea/ /node_modules/ +/test/report/*.html +/test/report/*.json diff --git a/.travis.yml b/.travis.yml index ae0270f..288ac45 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,3 @@ language: node_js node_js: - - 0.12 \ No newline at end of file + - 7.10.0 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9a37a13 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ + +### 2.0.0 (2017-06-19) + +##### Support for Cucumber 2 + +* Cucumber 2 [PR#15](https://github.com/gkushang/cucumber-parallel/pull/15). + \ No newline at end of file diff --git a/README.md b/README.md index 7a6979d..b03b043 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,24 @@ -cucumber-parallel +Cucumber Parallel ================= +***Run Cucumber Features and Scenarios in Parallel*** -[![Build Status](https://travis-ci.org/gkushang/cucumber-parallel.svg?branch=develop)](https://travis-ci.org/gkushang/cucumber-parallel) +[![Build Status][travis-shield]][travis-link] [![npm][npm-shield]][npm-link] [![Dependency Status][depedency-shield]][depedency-link] [![License][license-shield]][license-link] -### Run Cucumber Features and Scenarios in Parallel +> For HTML Reporting, head over to [cucumber-html-reporter][cucumber-html-reporter] - -### Install +## Install ``` bash npm install cucumber-parallel --save-dev ``` +***Notes:*** + +* Latest version supports Cucumber 2 +* Install `cucumber-parallel@1.0.0` for cucumber version `< Cucumber@2` + -#### How to run Features/Scenarios in Parallel? +## Very simple to use ```bash @@ -40,18 +45,7 @@ $ node_modules/cucumber-parallel/bin/cucumber-parallel /path/to/features -r /pat ``` - -#### Format -Because it runs features/scenarios in parallel, it only supports JSON format. You can save the JSON output to file by passing the cucumber-format as, - - -```bash --f json:path/to/file.json -``` - - - -### Run +## Run Supports all the arguments as [cucumber-js][1], except `--format` as explained above @@ -59,7 +53,7 @@ Supports all the arguments as [cucumber-js][1], except `--format` as explained a $ node_modules/cucumber-parallel/bin/cucumber-parallel /path/to/features -r /path/to/step-defs -f json:path/to/file.json --tags=@myTag ``` -### Re-run failed scenarios in parallel +#### Re-run failed scenarios in parallel ```bash @@ -77,6 +71,17 @@ $ node_modules/cucumber-parallel/bin/cucumber-parallel /path/to/login.feature:10 ``` + +#### Format +Because it runs features/scenarios in parallel, it only supports JSON format. You can save the JSON output to file by passing the cucumber-format as, + + +```bash +-f json:path/to/file.json +``` + + + Above example will run login & signup features in parallel; two processes in parallel since two features are passed. Total 4 scenarios will run. You can run all 4 in parallel by passing as below, `/path/to/login.feature:10 /path/to/login.feature:20 /path/to/login.feature:25 path/to/signup.feature:18` @@ -84,7 +89,7 @@ Above example will run login & signup features in parallel; two processes in par ### HTML Reports -Run Features or Scenarios in Parallel and generate HTML Reports with [cucumber-html-reporter][6] +Run Features or Scenarios in Parallel and generate HTML Reports with [cucumber-html-reporter][cucumber-html-reporter] Cucumber-Parallel is also integrated with HTML reporting Grunt Cucumber module [grunt-cucumberjs][2] @@ -94,18 +99,35 @@ Sample HTML Reports: 2. [Foundation Theme Reports][4] 3. [Simple Theme Reports][5] +## Changelog + +[changelog][changelog] -### Proposed Enhancements -- Run Features Parallel : LIVE -- Run Scenarios Parallel : LIVE -- Limit number of workers : PENDING [1]: https://github.com/cucumber/cucumber-js "CucumberJs" [2]: https://www.npmjs.com/package/grunt-cucumberjs "grunt-cucummberjs" [3]: http://htmlpreview.github.io/?https://github.com/gkushang/cucumber-html-reporter/blob/develop/samples/html_reports/cucumber_report_bootstrap.html "Bootstrap Theme Reports" [4]: http://htmlpreview.github.io/?https://github.com/gkushang/cucumber-html-reporter/blob/develop/samples/html_reports/cucumber_report_foundation.html "Foundation Theme Reports" [5]: http://htmlpreview.github.io/?https://github.com/gkushang/cucumber-html-reporter/blob/develop/samples/html_reports/cucumber_report_simple.html "Simple Theme Reports" -[6]: https://www.npmjs.com/package/cucumber-html-reporter + +[cucumber-html-reporter]: https://www.npmjs.com/package/cucumber-html-reporter + +[changelog]: https://github.com/gkushang/cucumber-parallel/blob/develop/CHANGELOG.md + +[travis-shield]: https://travis-ci.org/gkushang/cucumber-parallel.svg?branch=develop +[travis-link]: https://travis-ci.org/gkushang/cucumber-parallel + +[npm-shield]: https://img.shields.io/npm/v/cucumber-parallel.svg +[npm-link]: https://www.npmjs.com/package/cucumber-parallel + +[depedency-shield]: https://david-dm.org/gkushang/cucumber-parallel.svg +[depedency-link]: https://david-dm.org/gkushang/cucumber-parallel + +[license-shield]: https://img.shields.io/github/license/mashape/apistatus.svg +[license-link]: https://github.com/gkushang/cucumber-parallel/ + + + diff --git a/lib/cucumber/cucumber_js.js b/lib/cucumber/cucumber_js.js index 60a799d..3bd341a 100644 --- a/lib/cucumber/cucumber_js.js +++ b/lib/cucumber/cucumber_js.js @@ -1,10 +1,26 @@ 'use strict'; +Object.defineProperty(exports, "__esModule", { + value: true +}); + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + var log = require('debug')('cucumber-parallel:cucumber_js'); var Cucumber = require('cucumber'); +var Cli = require('cucumber').Cli; +var ScenarioFilter = require('cucumber').ScenarioFilter; +var helpers = require('cucumber/lib/cli/helpers'); + +var runTime = _interopRequireDefault(require('cucumber').Runtime); var path = require('path'); var Command = require('commander').Command; var fs = require('fs'); +var slicedToArray = _interopRequireDefault(require('babel-runtime/helpers/slicedToArray')); +var bluebird = _interopRequireDefault(require('bluebird')); + module.exports = function cucumber_js() { @@ -39,16 +55,17 @@ module.exports = function cucumber_js() { .option('--parallel ', 'run parallel scenarios or features', collect, []) .option('--rerun ', 'reruning the failed scenarios or features', collect, []); - - program.on('--help', function() { + program.on('--help', function () { console.log(' For more details please visit https://github.com/cucumber/cucumber-js#cli\n'); }); + program.parse(process.argv); + return program; } function reportFormatterOutputFile(formats) { - formats.forEach(function(format) { + formats.forEach(function (format) { process.send({ info: 'formatter', format: format @@ -56,78 +73,111 @@ module.exports = function cucumber_js() { }) } - function runCucumber() { + function exit(isSucceed) { + var code = isSucceed ? 0 : 1; - function getConfiguration() { - if (process.argv[2].match('node')) { - process.argv.splice(2, 1); - process.argv.splice(2, 1); - } + process.send({ + info: 'report', + report: report, + succeeded: isSucceed, + code: code + }); - var program = getProgram(); + function exitNow() { + log('exiting with code: ' + code); + process.exit(code); + } - program.parse(process.argv); + function exitAfterTimeOut() { + setTimeout(exitNow, 10000); + } - var profileArgs = Cucumber.Cli.ProfilesLoader.getArgs(program.profile); + if (process.stdout.write('')) { + exitAfterTimeOut(); + } else { + process.stdout.on('drain', exitAfterTimeOut); + } + } - if (profileArgs.length > 0) { - var fullArgs = process.argv.slice(0, 2).concat(profileArgs).concat(process.argv.slice(2)); - program = getProgram(); - program.parse(fullArgs); - } + function run(obj) { + return function (options) { - var features = []; - var options = program.opts(); - features.push(process.argv[process.argv.length - 1]); - reportFormatterOutputFile(options.format); - return Cucumber.Cli.Configuration(options, features); - } + var ref = (0, slicedToArray.default)(options, 2); + var features = ref[0]; + var ref$ = ref[1]; + var cleanup = ref$.cleanup; + var formatters = ref$.formatters; - var configuration = getConfiguration(); + var JsonFormatter = formatters[1]; - var runtime = Cucumber.Runtime(configuration); + JsonFormatter.log = function (value) { + report.push(value.slice(1, -1)); + }; - var logToFunction = function(value) { - report.push(value.slice(1, -1)); - }; + var runtime = new runTime.default({ + features: features, + listeners: formatters, + options: getProgram().opts(), + supportCodeLibrary: obj.supportCodeLibrary + }); - var formatter = Cucumber.Listener.JsonFormatter( - { - stream: process.stdout, - logToFunction: logToFunction - } - ); - runtime.attachListener(formatter); + var isSucceed = runtime.start(); - runtime.start(function(succeeded) { + cleanup(); - var code = succeeded ? 0 : 1; + return isSucceed; + } + } - process.send({ - info: 'report', - report: report, - succeeded: succeeded, - code: code + function applyConfigurationAndRun(cli) { + + return function (configuration) { + + reportFormatterOutputFile(getProgram().opts().format); + + var scenarioFilter = new ScenarioFilter(configuration.scenarioFilterOptions); + + var supportCodeLibrary = cli.getSupportCodeLibrary(configuration.supportCodePaths); + + var formatters = cli.getFormatters({ + formatOptions: configuration.formatOptions, + formats: configuration.formats, + supportCodeLibrary: supportCodeLibrary }); - function exitNow() { - log('exiting with code: ' + code); - process.exit(code); - } + var _ref8 = bluebird.default.all([(0, helpers.getFeatures)({ + featurePaths: configuration.featurePaths, + scenarioFilter: scenarioFilter + }), formatters]); - function exitAfterTimeOut() { - setTimeout(exitNow, 5000); - } + return _ref8.then(run({supportCodeLibrary: supportCodeLibrary})) + } + } - if (process.stdout.write('')) { - exitAfterTimeOut(); - } else { - process.stdout.on('drain', exitAfterTimeOut); + function runCucumber() { + function removeNodeArgFromProcessArgs() { + if (process.argv[2].match('node')) { + process.argv.splice(2, 1); + process.argv.splice(2, 1); } + } + + removeNodeArgFromProcessArgs(); + + var cwd = process.cwd(); + var argv = process.argv; + var stdout = process.stdout; + var cli = new Cli({ + argv: argv, + cwd: cwd, + stdout: stdout }); - } + return cli.getConfiguration() + .then(applyConfigurationAndRun(cli)) + .then(exit); + } return { getProgram: getProgram, diff --git a/lib/parallelizer/parallelizer.js b/lib/parallelizer/parallelizer.js index 8f04214..f83d86c 100644 --- a/lib/parallelizer/parallelizer.js +++ b/lib/parallelizer/parallelizer.js @@ -9,7 +9,7 @@ var path = require('path'); var fs = require('fs'); var colors = require('colors'); -module.exports = function() { +module.exports = function () { var cucumberProgram; var cucumberJs; @@ -20,26 +20,26 @@ module.exports = function() { var eventEmitter = new Events.EventEmitter(); - eventEmitter.on('run', function() { + eventEmitter.on('run', function () { forkRunner({feature: tasks.shift()}); eventEmitter.emit('next'); }); - eventEmitter.on('next', function() { + eventEmitter.on('next', function () { if (tasks.length > 0) { eventEmitter.emit('run'); } }); - eventEmitter.on('invoke', function() { + eventEmitter.on('invoke', function () { eventEmitter.emit('initialize'); }); - eventEmitter.on('report', function(message) { + eventEmitter.on('report', function (message) { Reporter.inform(message); }); - eventEmitter.on('initialize', function() { + eventEmitter.on('initialize', function () { log('_argv: ', _argv); cucumberProgram = cucumberJs.getProgram(); cucumberProgram.parse(_argv); @@ -50,7 +50,7 @@ module.exports = function() { }); function exit() { - if(Reporter.getResults().succeeded) { + if (Reporter.getResults().succeeded) { console.log(Reporter.CUCUMBER_PARALLEL + 'Done, all scenarios passed without error'.bold.green); } else { console.log(Reporter.CUCUMBER_PARALLEL + 'Failed scenarios, please see the report'.bold.red); @@ -59,10 +59,14 @@ module.exports = function() { } function done() { + function exitDone() { + exit(); + } + if (runnerIndex === 0) { - Reporter.report(Tasks.getParallelType()).then(function() { - exit(); - }) + Reporter.report(Tasks.getParallelType()) + .then(exitDone); + } else { Reporter.report(Tasks.getParallelType()); } @@ -71,7 +75,7 @@ module.exports = function() { function forkRunner(options) { var runner; - _argv.push(options.feature); + _argv[2] = (options.feature); if (options.feature.length > 0) { runnerIndex++; @@ -80,7 +84,7 @@ module.exports = function() { log('starting runner ', ++index); - runner.on('message', function(message) { + runner.on('message', function (message) { log('message received. runner is', runnerIndex, 'and message is', message); diff --git a/lib/parallelizer/reporter.js b/lib/parallelizer/reporter.js index af3cedd..b65405c 100644 --- a/lib/parallelizer/reporter.js +++ b/lib/parallelizer/reporter.js @@ -41,44 +41,60 @@ module.exports = function reporter() { } function processResults(parallelType) { - return new Promise(function(resolve, reject) { - var results = []; + return new Promise(function (resolve, reject) { + var newResults = []; - featureResults.forEach(function(feature) { + featureResults.forEach(function (feature) { try { - var existingResult = JSON.parse(feature); + var existingResult = feature; + if (parallelType === ParallelTypes.SCENARIOS) { - var index = findIndex(results, function(result) { - return result.uri === existingResult.uri; + + var existingResultObject = JSON.parse(existingResult); + + var index = findIndex(newResults, function (result) { + return JSON.stringify(result).includes(existingResultObject.uri); }); if (index !== -1) { - if (existingResult.elements && existingResult.elements.length > 0) { - if (results[index].elements) { - results[index].elements.push(existingResult.elements[0]); + + var newResultJSON = JSON.parse(newResults[index]); + + if (existingResultObject.elements && existingResultObject.elements.length > 0) { + if (newResultJSON.elements) { + newResultJSON.elements.push(existingResultObject.elements[0]); } else { - results[index].elements = existingResult.elements; + newResultJSON.elements = existingResultObject.elements[0]; } + + newResults[index] = JSON.stringify(newResultJSON,null, 2); } + } else { - results.push(existingResult); + newResults.push(existingResult); } + } else { - results.push(existingResult); + newResults.push(existingResult); } + } catch (e) { - reject(e); + return reject(e); } }); - resolve(results); + return resolve(newResults); }) } function report(parallelType) { - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { + function rejectPromise(e) { + return reject(e); + } + function done(results) { - var jsonFormatted = JSON.stringify(results, null, 2); + var jsonFormatted = '[' + results + ']'; log(jsonFormatted); if (outputToFile.length > 0) { try { @@ -97,9 +113,7 @@ module.exports = function reporter() { return processResults(parallelType) .then(done) - .catch(function(e) { - return reject(e); - }) + .catch(rejectPromise); }); } @@ -110,4 +124,4 @@ module.exports = function reporter() { formatterOutputFile: formatterOutputFile, CUCUMBER_PARALLEL: CUCUMBER_PARALLEL } -}; \ No newline at end of file +}; diff --git a/lib/tasker/parser.js b/lib/tasker/parser.js index ed8a55b..6e6105e 100644 --- a/lib/tasker/parser.js +++ b/lib/tasker/parser.js @@ -22,4 +22,4 @@ function parser(feature) { return _this; } -module.exports = parser; \ No newline at end of file +module.exports = parser; \ No newline at end of file diff --git a/lib/tasker/tasks.js b/lib/tasker/tasks.js index ebb2255..6276640 100644 --- a/lib/tasker/tasks.js +++ b/lib/tasker/tasks.js @@ -14,10 +14,10 @@ module.exports = function tasks() { return options.featureFilePath + ':' + scenario.location.line; } - options.feature.scenarioDefinitions.forEach(function(scenario) { + options.feature.feature.children.forEach(function (scenario) { if (scenario.examples) { - scenario.examples.forEach(function(example) { - example.tableBody.forEach(function(tableRow) { + scenario.examples.forEach(function (example) { + example.tableBody.forEach(function (tableRow) { scenarios.push(scenarioAsString(tableRow)); }); }); @@ -48,7 +48,7 @@ module.exports = function tasks() { parallelType = parallelRunType; } - getFeatures(fromDirectory).forEach(function(featureFilePath) { + getFeatures(fromDirectory).forEach(function (featureFilePath) { var parser = Parser(featureFilePath); if (parser.isSucceeded) { processScenarios({ diff --git a/package.json b/package.json index 19cb0a2..9ba2eef 100644 --- a/package.json +++ b/package.json @@ -7,27 +7,30 @@ "email": "g.kushang@gmail.com" }, "scripts": { - "pretest": "npm run parallel-features & npm run assert-report", - "test": "npm run parallel-scenarios & npm run assert-report", - "posttest": "rm -r test/report/*.json", + "pretest": "npm run clean && npm run parallel-features && npm run assert-report", + "test": "npm run clean && npm run parallel-scenarios", + "posttest": "npm run generate-report && npm run assert-report", "parallel-features": "node test/bin/cucumber-parallel test/features/ -f json:test/report/cucumber_report.json --parallel features", "parallel-scenarios": "node test/bin/cucumber-parallel test/features/ -f json:test/report/cucumber_report.json --parallel scenarios", - "assert-report": "node test/features/assert/assertReport.js" + "assert-report": "node test/features/assert/assertReport.js", + "clean": "rm -rf test/report/*.html test/report/cucumber_report.json test/report/*.json test/report/screenshot", + "generate-report": "node test/report/generateReport.js" }, "devDependencies": { - "chai": "^1.10.0", - "chai-fs": "^0.1.0", - "cucumber": "^1.3.1", - "cucumber-html-reporter": "^0.2.1" + "chai": "^4.0.2", + "chai-fs": "^1.0.0", + "cucumber-html-reporter": "^2.0.0" }, "dependencies": { - "bluebird": "^3.0.5", + "babel-runtime": "^6.23.0", + "bluebird": "^3.5.0", "colors": "^1.1.2", "commander": "^2.9.0", + "cucumber": "^2.3.0", "debug": "^2.2.0", - "events": "^1.1.0", + "events": "^1.1.1", "fs-finder": "^1.8.1", - "gherkin": "^3.2.0", + "gherkin": "^4.1.3", "lodash.findindex": "^4.2.0" }, "repository": { @@ -38,6 +41,7 @@ "url": "https://github.com/gkushang/cucumber-parallel/issues", "email": "g.kushang@gmail.com" }, + "license": "MIT", "keywords": [ "cucumber", "parallel", diff --git a/test/config/config.json b/test/config/config.json index 447a86b..3dda922 100644 --- a/test/config/config.json +++ b/test/config/config.json @@ -1,5 +1,8 @@ { "Scenarios": { "totalScenarios": 8 + }, + "ScenariosPerFeature": { + "totalScenarios": 4 } } \ No newline at end of file diff --git a/test/features/assert/assertReport.js b/test/features/assert/assertReport.js index 911b1be..f7e7657 100644 --- a/test/features/assert/assertReport.js +++ b/test/features/assert/assertReport.js @@ -1,2 +1,2 @@ 'use strict'; -setTimeout(require('././report').assert, 5000); \ No newline at end of file +setTimeout(require('./report').assert, 1000); \ No newline at end of file diff --git a/test/features/assert/report.js b/test/features/assert/report.js index 0a375a7..ac313b2 100644 --- a/test/features/assert/report.js +++ b/test/features/assert/report.js @@ -7,7 +7,7 @@ var config = require('../../config/config.json'); module.exports = { - assert: function() { + assert: function () { var cucumberReportJson = 'cucumber_report.json'; var jsonFile = 'test/report/' + cucumberReportJson; @@ -17,14 +17,20 @@ module.exports = { //verify number of scenarios var numberOfScenarios = 0; - jsonOutput.forEach(function(feature) { + jsonOutput.forEach(function (feature) { numberOfScenarios += feature.elements.length; }); expect(numberOfScenarios).to.be.equal(config.Scenarios.totalScenarios, 'Scenarios are missing in the report'); - // verify screenshot is attached to the report - expect(jsonOutputStringify).to.contain('mime_type":"image/png"', 'screenshot was not attached to report'); + expect(numberOfScenarios).to.be.equal(config.Scenarios.totalScenarios, 'Scenarios are missing in the report'); + + expect(jsonOutput[0].elements.length).to.be.equal(config.ScenariosPerFeature.totalScenarios, 'Scenarios per feature are not mapped correctly'); + + expect(jsonOutput[1].elements.length).to.be.equal(config.ScenariosPerFeature.totalScenarios, 'Scenarios per feature are not mapped correctly'); + + // verify screenshots is attached to the report + expect(jsonOutputStringify).to.contain('mime_type":"image/png"', 'screenShot was not attached to report'); // verify test data is attached to the report expect(jsonOutputStringify).to.contain('mime_type":"text/plain"', 'test data was not attached to report'); diff --git a/test/features/parallel_1.feature b/test/features/parallel_1.feature index 3b19b2a..d54b9bd 100644 --- a/test/features/parallel_1.feature +++ b/test/features/parallel_1.feature @@ -5,13 +5,13 @@ Feature: Cucumber Parallel Set One Wants to run Cucumber Features in Parallel using cucumber-parallel module @happy - Scenario: Fred runs features in parallel + Scenario: (set-one) Fred runs features in parallel Given Fred has multiple features written in cucumber When he runs the features in parallel with "--parallel features" using cucumber-parallel module Then all the features should run in parallel @dataTable - Scenario: Fred runs features in parallel with data-tables + Scenario: (set-one) Fred runs features in parallel with data-tables Given Fred has a step with below data table | id | name | | 1 | data-A | @@ -20,7 +20,7 @@ Feature: Cucumber Parallel Set One Then all the features should run in parallel @scenarioOutline - Scenario Outline: Fred runs features in parallel with scenario outline + Scenario Outline: (set-one) Fred runs features in parallel with scenario outline Given Fred has scenario outline with the "" When he runs the features in parallel with "--parallel features" using cucumber-parallel module Then all the features should run in parallel diff --git a/test/features/parallel_2.feature b/test/features/parallel_2.feature index 49191ed..1c217a7 100644 --- a/test/features/parallel_2.feature +++ b/test/features/parallel_2.feature @@ -5,13 +5,13 @@ Feature: Cucumber Parallel Set Two Wants to run Cucumber Scenarios in Parallel using cucumber-parallel module @happy - Scenario: Fred runs scenarios in parallel + Scenario: (set-two) Fred runs scenarios in parallel Given Fred has multiple scenarios written in cucumber When he runs the features in parallel with "--parallel scenarios" using cucumber-parallel module Then all the scenarios should run in parallel @dataTable - Scenario: Fred runs scenarios in parallel with data-tables + Scenario: (set-two) Fred runs scenarios in parallel with data-tables Given Fred has a step with below data table | id | name | | 1 | data-A | @@ -20,7 +20,7 @@ Feature: Cucumber Parallel Set Two Then all the scenarios should run in parallel @scenarioOutline - Scenario Outline: Fred runs scenarios in parallel with scenario outline + Scenario Outline: (set-two) Fred runs scenarios in parallel with scenario outline Given Fred has scenario outline with the "" When he runs the features in parallel with "--parallel scenarios" using cucumber-parallel module Then all the scenarios should run in parallel diff --git a/test/features/step_definitions/parallelStepDefs.js b/test/features/step_definitions/parallelStepDefs.js index 1ad4f3b..fe6cae3 100644 --- a/test/features/step_definitions/parallelStepDefs.js +++ b/test/features/step_definitions/parallelStepDefs.js @@ -1,43 +1,31 @@ 'use strict'; -var htmlReporter = require('cucumber-html-reporter'); +var {defineSupportCode} = require('cucumber'); -module.exports = function parallelStepDefs() { - this.Before(function(scenario, callback) { +defineSupportCode(function ({Before, Given, Then, When}) { + Before(function (scenario, callback) { this.scenario = scenario; callback(); }); - this.Given(/^Fred has multiple (?:features|scenarios) written in cucumber$/, function (callback) { - this.scenario.attach(new Buffer('').toString('base64'), 'image/png'); + Given(/^Fred has multiple (?:features|scenarios) written in cucumber$/, function (callback) { + this.attach('', 'image/png'); callback(); }); - this.When(/^he runs the features in parallel with "([^"]*)" using cucumber\-parallel module$/, function (testData, callback) { - this.scenario.attach(testData); + When(/^he runs the features in parallel with "([^"]*)" using cucumber\-parallel module$/, function (testData, callback) { + this.attach(testData); callback(); }); - this.Then(/^all the (?:features|scenarios) should run in parallel$/, function (callback) { + Then(/^all the (?:features|scenarios) should run in parallel$/, function (callback) { callback(); }); - this.When(/^Fred has scenario outline with the "([^"]*)"$/, function (id, callback) { + When(/^Fred has scenario outline with the "([^"]*)"$/, function (id, callback) { callback(); }); - this.Given(/^Fred has a step with below data table$/, function (table, callback) { - // Write code here that turns the phrase above into concrete actions + Given(/^Fred has a step with below data table$/, function (table, callback) { callback(); }); - - this.registerHandler('AfterFeatures', function(event, callback) { - htmlReporter.generate({ - theme: 'bootstrap', - jsonFile: 'test/report/cucumber_report.json', - output: 'test/report/cucumber_report.html', - reportSuiteAsScenarios: true - }); - callback(); - }); - -}; +}); diff --git a/test/report/.gitignore b/test/report/.gitignore new file mode 100644 index 0000000..7597608 --- /dev/null +++ b/test/report/.gitignore @@ -0,0 +1 @@ +/screenshot/ diff --git a/test/report/cucumber_report.json b/test/report/cucumber_report.json deleted file mode 100644 index f7b00e5..0000000 --- a/test/report/cucumber_report.json +++ /dev/null @@ -1,658 +0,0 @@ -[ - { - "description": " In order to have the quick regression with Cucumber\n Fred, a cucumber user\n Wants to run Cucumber Features in Parallel using cucumber-parallel module", - "elements": [ - { - "id": "cucumber-parallel-set-one;fred-runs-features-in-parallel", - "keyword": "Scenario", - "line": 8, - "name": "Fred runs features in parallel", - "steps": [ - { - "arguments": [], - "keyword": "Before ", - "result": { - "status": "passed", - "duration": 2817972 - }, - "hidden": true, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:4" - } - }, - { - "arguments": [], - "keyword": "Given ", - "name": "Fred has multiple features written in cucumber", - "result": { - "status": "passed", - "duration": 1762893 - }, - "line": 9, - "embeddings": [ - { - "data": "", - "mime_type": "image/png" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:9" - } - }, - { - "arguments": [], - "keyword": "When ", - "name": "he runs the features in parallel with \"--parallel features\" using cucumber-parallel module", - "result": { - "status": "passed", - "duration": 433012 - }, - "line": 10, - "embeddings": [ - { - "data": "LS1wYXJhbGxlbCBmZWF0dXJlcw==", - "mime_type": "text/plain" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:14" - } - }, - { - "arguments": [], - "keyword": "Then ", - "name": "all the features should run in parallel", - "result": { - "status": "passed", - "duration": 236183 - }, - "line": 11, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:19" - } - } - ], - "tags": [ - { - "name": "@happy", - "line": 7 - } - ], - "type": "scenario" - }, - { - "id": "cucumber-parallel-set-one;fred-runs-features-in-parallel-with-scenario-outline", - "keyword": "Scenario", - "line": 30, - "name": "Fred runs features in parallel with scenario outline", - "steps": [ - { - "arguments": [], - "keyword": "Before ", - "result": { - "status": "passed", - "duration": 2718248 - }, - "hidden": true, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:4" - } - }, - { - "arguments": [], - "keyword": "Given ", - "name": "Fred has scenario outline with the \"1\"", - "result": { - "status": "passed", - "duration": 1081727 - }, - "line": 24, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:23" - } - }, - { - "arguments": [], - "keyword": "When ", - "name": "he runs the features in parallel with \"--parallel features\" using cucumber-parallel module", - "result": { - "status": "passed", - "duration": 640085 - }, - "line": 25, - "embeddings": [ - { - "data": "LS1wYXJhbGxlbCBmZWF0dXJlcw==", - "mime_type": "text/plain" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:14" - } - }, - { - "arguments": [], - "keyword": "Then ", - "name": "all the features should run in parallel", - "result": { - "status": "passed", - "duration": 220242 - }, - "line": 26, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:19" - } - } - ], - "tags": [ - { - "name": "@scenarioOutline", - "line": 22 - } - ], - "type": "scenario" - }, - { - "id": "cucumber-parallel-set-one;fred-runs-features-in-parallel-with-data-tables", - "keyword": "Scenario", - "line": 14, - "name": "Fred runs features in parallel with data-tables", - "steps": [ - { - "arguments": [], - "keyword": "Before ", - "result": { - "status": "passed", - "duration": 2766842 - }, - "hidden": true, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:4" - } - }, - { - "arguments": [ - { - "rows": [ - { - "cells": [ - "id", - "name" - ] - }, - { - "cells": [ - "1", - "data-A" - ] - }, - { - "cells": [ - "2", - "data-B" - ] - } - ] - } - ], - "keyword": "Given ", - "name": "Fred has a step with below data table", - "result": { - "status": "passed", - "duration": 1195334 - }, - "line": 15, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:27" - } - }, - { - "arguments": [], - "keyword": "When ", - "name": "he runs the features in parallel with \"--parallel features\" using cucumber-parallel module", - "result": { - "status": "passed", - "duration": 661140 - }, - "line": 19, - "embeddings": [ - { - "data": "LS1wYXJhbGxlbCBmZWF0dXJlcw==", - "mime_type": "text/plain" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:14" - } - }, - { - "arguments": [], - "keyword": "Then ", - "name": "all the features should run in parallel", - "result": { - "status": "passed", - "duration": 174086 - }, - "line": 20, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:19" - } - } - ], - "tags": [ - { - "name": "@dataTable", - "line": 13 - } - ], - "type": "scenario" - }, - { - "id": "cucumber-parallel-set-one;fred-runs-features-in-parallel-with-scenario-outline", - "keyword": "Scenario", - "line": 31, - "name": "Fred runs features in parallel with scenario outline", - "steps": [ - { - "arguments": [], - "keyword": "Before ", - "result": { - "status": "passed", - "duration": 2949749 - }, - "hidden": true, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:4" - } - }, - { - "arguments": [], - "keyword": "Given ", - "name": "Fred has scenario outline with the \"2\"", - "result": { - "status": "passed", - "duration": 1111903 - }, - "line": 24, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:23" - } - }, - { - "arguments": [], - "keyword": "When ", - "name": "he runs the features in parallel with \"--parallel features\" using cucumber-parallel module", - "result": { - "status": "passed", - "duration": 859144 - }, - "line": 25, - "embeddings": [ - { - "data": "LS1wYXJhbGxlbCBmZWF0dXJlcw==", - "mime_type": "text/plain" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:14" - } - }, - { - "arguments": [], - "keyword": "Then ", - "name": "all the features should run in parallel", - "result": { - "status": "passed", - "duration": 161526 - }, - "line": 26, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:19" - } - } - ], - "tags": [ - { - "name": "@scenarioOutline", - "line": 22 - } - ], - "type": "scenario" - } - ], - "id": "cucumber-parallel-set-one", - "keyword": "Feature", - "line": 1, - "name": "Cucumber Parallel Set One", - "tags": [], - "uri": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/parallel_1.feature" - }, - { - "description": " In order to have the quick regression with Cucumber\n Fred, a cucumber user\n Wants to run Cucumber Scenarios in Parallel using cucumber-parallel module", - "elements": [ - { - "id": "cucumber-parallel-set-two;fred-runs-scenarios-in-parallel-with-scenario-outline", - "keyword": "Scenario", - "line": 30, - "name": "Fred runs scenarios in parallel with scenario outline", - "steps": [ - { - "arguments": [], - "keyword": "Before ", - "result": { - "status": "passed", - "duration": 2709607 - }, - "hidden": true, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:4" - } - }, - { - "arguments": [], - "keyword": "Given ", - "name": "Fred has scenario outline with the \"1\"", - "result": { - "status": "passed", - "duration": 1076867 - }, - "line": 24, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:23" - } - }, - { - "arguments": [], - "keyword": "When ", - "name": "he runs the features in parallel with \"--parallel scenarios\" using cucumber-parallel module", - "result": { - "status": "passed", - "duration": 977618 - }, - "line": 25, - "embeddings": [ - { - "data": "LS1wYXJhbGxlbCBzY2VuYXJpb3M=", - "mime_type": "text/plain" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:14" - } - }, - { - "arguments": [], - "keyword": "Then ", - "name": "all the scenarios should run in parallel", - "result": { - "status": "passed", - "duration": 229518 - }, - "line": 26, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:19" - } - } - ], - "tags": [ - { - "name": "@scenarioOutline", - "line": 22 - } - ], - "type": "scenario" - }, - { - "id": "cucumber-parallel-set-two;fred-runs-scenarios-in-parallel-with-scenario-outline", - "keyword": "Scenario", - "line": 31, - "name": "Fred runs scenarios in parallel with scenario outline", - "steps": [ - { - "arguments": [], - "keyword": "Before ", - "result": { - "status": "passed", - "duration": 3103050 - }, - "hidden": true, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:4" - } - }, - { - "arguments": [], - "keyword": "Given ", - "name": "Fred has scenario outline with the \"2\"", - "result": { - "status": "passed", - "duration": 1894862 - }, - "line": 24, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:23" - } - }, - { - "arguments": [], - "keyword": "When ", - "name": "he runs the features in parallel with \"--parallel scenarios\" using cucumber-parallel module", - "result": { - "status": "passed", - "duration": 427956 - }, - "line": 25, - "embeddings": [ - { - "data": "LS1wYXJhbGxlbCBzY2VuYXJpb3M=", - "mime_type": "text/plain" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:14" - } - }, - { - "arguments": [], - "keyword": "Then ", - "name": "all the scenarios should run in parallel", - "result": { - "status": "passed", - "duration": 222817 - }, - "line": 26, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:19" - } - } - ], - "tags": [ - { - "name": "@scenarioOutline", - "line": 22 - } - ], - "type": "scenario" - }, - { - "id": "cucumber-parallel-set-two;fred-runs-scenarios-in-parallel", - "keyword": "Scenario", - "line": 8, - "name": "Fred runs scenarios in parallel", - "steps": [ - { - "arguments": [], - "keyword": "Before ", - "result": { - "status": "passed", - "duration": 1830646 - }, - "hidden": true, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:4" - } - }, - { - "arguments": [], - "keyword": "Given ", - "name": "Fred has multiple scenarios written in cucumber", - "result": { - "status": "passed", - "duration": 1656872 - }, - "line": 9, - "embeddings": [ - { - "data": "", - "mime_type": "image/png" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:9" - } - }, - { - "arguments": [], - "keyword": "When ", - "name": "he runs the features in parallel with \"--parallel scenarios\" using cucumber-parallel module", - "result": { - "status": "passed", - "duration": 427989 - }, - "line": 10, - "embeddings": [ - { - "data": "LS1wYXJhbGxlbCBzY2VuYXJpb3M=", - "mime_type": "text/plain" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:14" - } - }, - { - "arguments": [], - "keyword": "Then ", - "name": "all the scenarios should run in parallel", - "result": { - "status": "passed", - "duration": 260582 - }, - "line": 11, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:19" - } - } - ], - "tags": [ - { - "name": "@happy", - "line": 7 - } - ], - "type": "scenario" - }, - { - "id": "cucumber-parallel-set-two;fred-runs-scenarios-in-parallel-with-data-tables", - "keyword": "Scenario", - "line": 14, - "name": "Fred runs scenarios in parallel with data-tables", - "steps": [ - { - "arguments": [], - "keyword": "Before ", - "result": { - "status": "passed", - "duration": 1834986 - }, - "hidden": true, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:4" - } - }, - { - "arguments": [ - { - "rows": [ - { - "cells": [ - "id", - "name" - ] - }, - { - "cells": [ - "1", - "data-A" - ] - }, - { - "cells": [ - "2", - "data-B" - ] - } - ] - } - ], - "keyword": "Given ", - "name": "Fred has a step with below data table", - "result": { - "status": "passed", - "duration": 666726 - }, - "line": 15, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:27" - } - }, - { - "arguments": [], - "keyword": "When ", - "name": "he runs the features in parallel with \"--parallel features\" using cucumber-parallel module", - "result": { - "status": "passed", - "duration": 379275 - }, - "line": 19, - "embeddings": [ - { - "data": "LS1wYXJhbGxlbCBmZWF0dXJlcw==", - "mime_type": "text/plain" - } - ], - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:14" - } - }, - { - "arguments": [], - "keyword": "Then ", - "name": "all the scenarios should run in parallel", - "result": { - "status": "passed", - "duration": 137954 - }, - "line": 20, - "match": { - "location": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/step_definitions/parallelStepDefs.js:19" - } - } - ], - "tags": [ - { - "name": "@dataTable", - "line": 13 - } - ], - "type": "scenario" - } - ], - "id": "cucumber-parallel-set-two", - "keyword": "Feature", - "line": 1, - "name": "Cucumber Parallel Set Two", - "tags": [], - "uri": "/Users/kugajjar/Documents/workspace/cucumber-parallel/test/features/parallel_2.feature" - } -] \ No newline at end of file diff --git a/test/report/generateReport.js b/test/report/generateReport.js new file mode 100644 index 0000000..bd7a8a7 --- /dev/null +++ b/test/report/generateReport.js @@ -0,0 +1,9 @@ +var htmlReporter = require('cucumber-html-reporter'); + +module.exports = htmlReporter.generate({ + theme: 'bootstrap', + jsonFile: 'test/report/cucumber_report.json', + output: 'test/report/cucumber_report.html', + launchReport: true, + reportSuiteAsScenarios: true +});