15

I am using Protractor with Cucumber (js). I would like to generate report files just like with the Cucumber-JVM version. I have seen examples when using Protractor with Jasmine, but practically nothing with Cucumber.

How do you generate reports when using this configuration?

The final goal is to publish this report in Jenkins, or anywhere else if they are directly generated in HTML.

Thanks!

Pedro Lopez
  • 2,236
  • 2
  • 19
  • 27
  • same use case, no answer yet but looking around... – mojjj Nov 06 '14 at 14:26
  • Have you tried this one: https://www.npmjs.com/package/cucumber-junit ? – Sergey Teplyakov Feb 19 '15 at 21:14
  • The thing is, because I am using Protractor, I cannot redirect the output like cucumber-junit suggests. Although, the latest version of protractor solves this issue and you can finally redirect the output and generate a JSON file that you can process with protractor-cucumber-junit and get an XML. Thanks. – Pedro Lopez Feb 19 '15 at 23:59
  • Also worth a look is `gulp-protractor-cucumber-html-report` – Lee Goddard Apr 27 '16 at 12:52
  • You might want to have a look at [Serenity/JS](http://serenity-js.org), which can compliment your current Protractor/Cucumber setup to generate the illustrated HTML reports automatically - [see this answer for instructions](http://stackoverflow.com/questions/34821016/is-there-a-protractor-reporting-tool-that-works-with-a-cucumber-framework/42598696#42598696) – Jan Molak Mar 04 '17 at 17:18

4 Answers4

12

With the latest version of protractor (from version 1.5.0), you can now generate a JSON report. When I asked this question about 7 months ago that feature was not there.

All you need to do is add this to your protractor-config.json file.

resultJsonOutputFile: 'report.json'

Where report.json is the location of the output file.

Once you have that, you can use protractor-cucumber-junit (https://www.npmjs.com/package/protractor-cucumber-junit), cucumberjs-junitxml (https://github.com/sonyschan/cucumberjs-junitxml) or something similar to transform the JSON file into a valid XML file that Jenkins can display.

$ cat report.json | ./node_modules/.bin/cucumber-junit > report.xml

Hope this helps.

Pedro Lopez
  • 2,236
  • 2
  • 19
  • 27
8

You can use cucumber-html-report to convert a json report to HTML. Add cucumber-html-report to your project with

$ npm install cucumber-html-report --save-dev

If you use protractor you can add the following code to hooks.js to

  • Take a browser screenshot after each failed scenario to be attached to the json report in the After-hook.
  • Write the test results to a json-file even if your cucumber opts format property says 'pretty'.
  • Convert the json report to HTML, including screenshots for failed scenarios.

var outputDir = 'someDir';
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();
  }
});

var createHtmlReport = function(sourceJson) {
  var CucumberHtmlReport = require('cucumber-html-report');
  var report = new CucumberHtmlReport({
    source: sourceJson, // source json
    dest: outputDir // target directory (will create if not exists)
  });
  report.createReport();
};

var JsonFormatter = Cucumber.Listener.JsonFormatter();
JsonFormatter.log = function(string) {
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir);
  }

  var targetJson = outputDir + 'cucumber_report.json';
  fs.writeFile(targetJson, string, function(err) {
    if (err) {
      console.log('Failed to save cucumber test results to json file.');
      console.log(err);
    } else {
      createHtmlReport(targetJson);
    }
  });
};

this.registerListener(JsonFormatter);
Ola
  • 150
  • 1
  • 6
  • I am getting the following error: [launcher] Error: TypeError: undefined is not a function at Object. (e2e/hooks.js:2:6) at Module._compile (module.js:460:26) at Object.Module._extensions..js (module.js:478:10) at Module.load (/Users/aaaa/.npm-packages/lib/node_modules/cucumber/node_modules/coffee-script/lib/coffee-script/register.js:45:36) at Function.Module._load (module.js:310:12) at Module.require (module.js:365:17) at require (module.js:384:17) – Fabio Nolasco Mar 04 '16 at 23:35
  • ... So I wrapper the hooks.js in a module.exports... but then it started to say [launcher] Error: ReferenceError: Cucumber is not defined ...... so I tried to make it lower case c (cucumber), but it still didn't work: Error: TypeError: Cannot read property 'JsonFormatter' of undefined – Fabio Nolasco Mar 04 '16 at 23:43
  • Can we use the logger to each steps? If so,how to acheive – Ashok kumar Ganesan Feb 20 '20 at 06:43
3

Try below code which is working for me:

You can use below plugin :

https://www.npmjs.com/package/cucumber-html-reporter

In package.json add below dependency as below:

   "cucumber-html-reporter": "^5.0.0"

hit command as below:

npm install

Add below import in your cucumberconfig.ts

import * as reporter from "cucumber-html-reporter"

Now add below key in cucumberconfig.ts

 onComplete: () => {
      //var reporter = require('cucumber-html-reporter');
      var options = {
        theme: 'bootstrap',
        jsonFile: './cucumberreport.json',
        output: './cucumberreportsss.html',
        reportSuiteAsScenarios: true,
        launchReport: true,
        metadata: {
            "App Version":"0.3.2",
            "Test Environment": "STAGING",
            "Browser": "Chrome  54.0.2840.98",
            "Platform": "Windows 10",
            "Parallel": "Scenarios",
            "Executed": "Remote"
        }
      };

      reporter.generate(options);
    },

Complete file is look like below:

import {Config} from 'protractor'
import * as reporter from "cucumber-html-reporter"

export let config: Config = {
    directConnect:true,
     // set to "custom" instead of cucumber.
    framework: 'custom',
    // path relative to the current config file
    frameworkPath: require.resolve('protractor-cucumber-framework'),
    seleniumAddress: 'http://localhost:4444/wd/hub',
    // To run script without cucumber use below
    //specs: ['typescriptscript.js'],

    onComplete: () => {
      //var reporter = require('cucumber-html-reporter');
      var options = {
        theme: 'bootstrap',
        jsonFile: './cucumberreport.json',
        output: './cucumberreportsss.html',
        reportSuiteAsScenarios: true,
        launchReport: true,
        metadata: {
            "App Version":"0.3.2",
            "Test Environment": "STAGING",
            "Browser": "Chrome  54.0.2840.98",
            "Platform": "Windows 10",
            "Parallel": "Scenarios",
            "Executed": "Remote"
        }
      };

      reporter.generate(options);
    },
    capabilities: {
        'browserName': 'firefox',
        'marionette': true,
        //shardTestFiles: true,
    },
    SELENIUM_PROMISE_MANAGER: false,
    specs: [
        '../Features/*.feature' // accepts a glob
      ],
    // Run feature file for cucumber use below
    cucumberOpts: {
        // require step definitions
        require: [
          './stepDefination/*.js' // accepts a glob
        ],
        format: 'json:cucumberreport.json',

      },

      jasmineNodeOpts: {
        showColors: true,
    },

}; 

To append failed screenshot use below code in hook

  After(function(scenarioResult) {
    let self = this;
    if (scenarioResult.result.status === Status.FAILED) {
    return browser.takeScreenshot()
    .then(function (screenshot) {
        const decodedImage = new Buffer(screenshot.replace(/^data:image\/png;base64,/, ''), 'base64');
        self.attach(decodedImage, 'image/png');
    });
}
});
Shubham Jain
  • 16,610
  • 15
  • 78
  • 125
  • Is there any way that report runs automatically in browser when ng run e2e command gets completed – Shikha Jan 16 '20 at 13:56
  • @ShubhamJain In the hook, we call this.attach, which is a call to world's attach function right ? My function just generate screenshot in report's folder, and I would like to Attach the screenshot into cucumber HTML report, I can't find a solution to this. Please explain how you implement the attach function (I mean real content not how you call it) Thank again for help ! – Deunz Feb 17 '20 at 08:11
  • Nevermind I found a way, I removed the attach code snippet from my custom world, and used the cucumber world constructor instead: code snippets here : https://stackoverflow.com/a/60278678/2376892 – Deunz Feb 18 '20 at 10:27
1

When using cucumber-html-report in the way the other answer indicates, you may run into issues on newer versions of Cucumber/Protractor/Cucumber-html-report.

The symptom is that the index.html is created but left empty at the end of a test run.

This is because cucumber-html-report is using an asynchronous file write and protractor is not waiting for it to complete. (We were using code which bears a striking resemblance to the code in the answer.)

This is a working setup:

in hooks.js keep the screen shot part the same from the other answer:

// Generate a screenshot at the end of each scenario (if failed; configurable to always)
cuke.After(function(scenario, done) {
    browser.getProcessedConfig().then(config => {
        if (!config.screenshots.onErrorOnly || scenario.isFailed()) {
            return browser.driver.takeScreenshot().then(function(png) {
                let decodedImage = new Buffer(png.replace(/^data:image\/(png|gif|jpeg);base64,/, ''), 'base64');
                scenario.attach(decodedImage, 'image/png');
                done();
            });
        } else {
            done();
        }
    });
});

in protractor.conf.js:

var cucumberReportDirectory = 'protractor-report';
var jsonReportFile = cucumberReportDirectory + '/cucumber_report.json';

exports.config = {
  cucumberOpts: {
    format: 'json:./' + jsonReportFile,
  },
  onCleanUp: function () {
      var CucumberHtmlReport = require('cucumber-html-report');

      return CucumberHtmlReport.create({
          source: jsonReportFile,
          dest: cucumberReportDirectory,
          title: 'OptiRoute - Protractor Test Run',
          component: new Date().toString()
      }).then(console.log).catch(console.log);
  },
  ignoreUncaughtExceptions: true,
  untrackOutstandingTimeouts: true
};

This is only the configuration directly related to cucumber-html-report the rest is seasoned to taste.

Make sure the report directory exists before you run the tests.

By putting the report creation here instead of attaching it as a Cucumber listener, Cucumber will wait for the asynchronous operation to complete before exiting.

Thank you to the Ola for the original answer, I discovered the async issue (the hard way) and was thinking I could save someone time when they find the same issue.

Hopasaurus
  • 41
  • 3