4

Task:

  • Perform an automated acceptance test using selenium, webdriver, cucumberjs.
  • Find a failing acceptance test scenario and take a screenshot of the page
  • Save that as an artefact in the go pipeline.

That was my task for the day. I have done all of that with writing the scenario test, selenium setup, go pipelines, and everything else needed.

The only problem is - I could not get a way to figure out how can I find a failing scenario step and take a screen shot of the page.

Problem details: I have the following code placed in my step definitions, which is run for every scenario step

//file: features/setpdefinitions/common.step.js

var commonWrapper = function commonWrapper() {

    this.World = require('../support/world').World;

    this.Before(function (next) {
        this.initBrowser(next);
    });

    this.After(function (next) {
        this.browser.quit(next);
    });

    this.StepResult(function (event, callback) {
        var stepResult = event.getPayloadItem('stepResult');
        console.log(stepResult.isFailed());
        callback();
    });
};

module.exports = commonWrapper;

the World contains the browser initiation methods.

and, this is a sample feature scenario that I am testing

Feature: Forgot Password
     As a user of Booking My account
     I want to reset my password
     So that I can login to my account when I forget my password

 Scenario: On unsuccessful entering invalid email id
    Given I am on forgot password page
    When I enter invalid email "invalidemail-someDomain.com"
        And click submit button
    Then I should see validation message "Please enter a valid email."

the problem is with the context data. I somehow could not get the scenario passed to the after/before method as the first argument. I tried the code given in the cucumberjs source but could not succeed. So, I moved onto adding the stepResult method, which run every time a step is completed. A relatively similar approach.

As per documentation, the isFailed() method returns a boolean based on the step result. but, I always get a false no matter the step failed or passed. I tried its alter-ego isSuccessful() which returns a true no matter what.

so,

  1. what could I be possibly doing wrong here?
  2. how do I actually pass the scenario to the after() method?

I'm relatively new to TDD, but hey it been a great experience so far.

Sanjeev
  • 1,838
  • 1
  • 16
  • 28

3 Answers3

7

What you need is an after hook

Create a file features/support/after_hooks.js

module.exports = function() {
    this.After(function (scenario, callback) {
        if (scenario.isFailed()) {
            // Do your after stuff here
        }
        callback();
    });
};

Note that this is only executed after every feature

Dominik Ehrenberg
  • 1,533
  • 1
  • 15
  • 12
1

You can get more details in (cucumberjs 1.x) https://github.com/cucumber/cucumber-js/blob/1.x/lib/cucumber/api/scenario.js#L27

getKeyword: function getKeyword() {
    return astScenario.getKeyword();
},
getName: function getName() {
    return astScenario.getName();
},
getDescription: function getDescription() {
    return astScenario.getDescription();
},
getUri: function getUri() {
    return astScenario.getUri();
},
getLine: function getLine() {
    return astScenario.getLine();
},
getTags: function getTags() {
    return astScenario.getTags();
},
isSuccessful: function isSuccessful() {
    return scenarioResult.getStatus() === Cucumber.Status.PASSED;
},
isFailed: function isFailed() {
    return scenarioResult.getStatus() === Cucumber.Status.FAILED;
},
isPending: function isPending() {
    return scenarioResult.getStatus() === Cucumber.Status.PENDING;
},
isUndefined: function isUndefined() {
    return scenarioResult.getStatus() === Cucumber.Status.UNDEFINED;
},
isSkipped: function isSkipped() {
    return scenarioResult.getStatus() === Cucumber.Status.SKIPPED;
},
getException: function getException() {
    return scenarioResult.getFailureException();
},
getAttachments: function getAttachments() {
    return attachments;
},
clearAttachments: function clearAttachments() {
    attachments = [];
},
Xotabu4
  • 3,063
  • 17
  • 29
0

Create afterhook.js and check for failing scenario You can use browser.saveScreenshot for saving the screenshot . While saving screenshot use a timestamp to the file name and also exclude the screenshots from version control

module.exports = function() {
  this.After((scenario, callback) => {
    if (scenario.isFailed()) {
      const d = new Date();
      browser.saveScreenshot(
        `./e2e/screenshots/screenshot-${d.toISOString()}.png`
      );
    }
    callback();
  });
};
  • what is the source of the "scenario" parameter? When I use scenario.isFailed() I get "isFailed()" is not a function error. – Kyon Perez Dec 15 '21 at 22:07