Skip to content

Latest commit

 

History

History
142 lines (104 loc) · 4.19 KB

hooks.md

File metadata and controls

142 lines (104 loc) · 4.19 KB

Hooks

Hooks are used for setup and teardown the environment before and after each scenario. See the API reference for the specification of the first argument passed to hooks. Multiple Before hooks are executed in the order that they were defined. Multiple After hooks are executed in the reverse order that they were defined.

Note that your hook functions cannot reference the world as this if you use arrow functions. See FAQ for details.

const {After, Before} = require('@cucumber/cucumber');

// Synchronous
Before(function () {
  this.count = 0;
});

// Asynchronous Callback
Before(function (testCase, callback) {
  var world = this;
  tmp.dir({unsafeCleanup: true}, function(error, dir) {
    if (error) {
      callback(error);
    } else {
      world.tmpDir = dir;
      callback();
    }
  });
});

// Asynchronous Promise
After(function () {
  // Assuming this.driver is a selenium webdriver
  return this.driver.quit();
});

Named hooks

ℹ️ Added in v8.1.0

Hooks can optionally be named:

const {Before} = require('@cucumber/cucumber');

Before({name: "Set up some test state"}, function () {
// do stuff here
});

Such hooks will then be referenced by name in formatter output, which can be useful to help you understand what's happening with your tests.

Tagged hooks

Hooks can be conditionally selected for execution based on the tags of the scenario.

const {After, Before} = require('@cucumber/cucumber');

Before(function () {
  // This hook will be executed before all scenarios
});

Before({tags: "@foo"}, function () {
  // This hook will be executed before scenarios tagged with @foo
});

Before({tags: "@foo and @bar"}, function () {
  // This hook will be executed before scenarios tagged with @foo and @bar
});

Before({tags: "@foo or @bar"}, function () {
  // This hook will be executed before scenarios tagged with @foo or @bar
});

// You can use the following shorthand when only specifying tags
Before("@foo", function () {
  // This hook will be executed before scenarios tagged with @foo
});

See more documentation on tag expressions

Skipping in a Before Hook

If you need to imperatively skip a test using a Before hook, this can be done using any of the constructs defined in skipped steps

This includes using: a synchronous return, an asynchronous callback, or an asynchronous promise

// Synchronous
Before(function() {
  // perform some runtime check to decide whether to skip the proceeding scenario
  return 'skipped'
});

BeforeAll / AfterAll

If you have some setup / teardown that needs to be done before or after all scenarios, use BeforeAll / AfterAll. Like hooks and steps, these can be synchronous, accept a callback, or return a promise.

Unlike Before / After these methods will not have a world instance as this. This is because each scenario gets its own world instance and these hooks run before / after all scenarios.

const {AfterAll, BeforeAll} = require('@cucumber/cucumber');

// Synchronous
BeforeAll(function () {
  // perform some shared setup
});

// Asynchronous Callback
BeforeAll(function (callback) {
  // perform some shared setup

  // execute the callback (optionally passing an error when done)
});

// Asynchronous Promise
AfterAll(function () {
  // perform some shared teardown
  return Promise.resolve()
});

BeforeStep / AfterStep

If you have some code execution that needs to be done before or after all steps, use BeforeStep / AfterStep. Like the Before / After hooks, these also have a world instance as 'this', and can be conditionally selected for execution based on the tags of the scenario.

const {AfterStep, BeforeStep} = require('@cucumber/cucumber');

BeforeStep({tags: "@foo"}, function () {
  // This hook will be executed before all steps in a scenario with tag @foo
});

AfterStep( function ({result}) {
  // This hook will be executed after all steps, and take a screenshot on step failure
  if (result.status === Status.FAILED) {
    this.driver.takeScreenshot();
  }
});