Cucumber HTML report with Protractor

2019-01-23 15:38发布

问题:

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!

回答1:

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.



回答2:

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);



回答3:

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.