Skip to content

Latest commit

 

History

History
159 lines (115 loc) · 4.69 KB

hooks.md

File metadata and controls

159 lines (115 loc) · 4.69 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.

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

World parameters in BeforeAll/AfterAll

ℹ️ Added in v10.1.0

BeforeAll/AfterAll hooks aren't given a World instance bound to this like other hooks and steps. But they can access World parameters via this.parameters in order to:

  • Use the parameters as configuration to drive automation
  • Update the parameters with extra context which will then be available to other hooks and steps

Here's a fictional example of obtaining an auth token that can then be used by all tests:

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

BeforeAll(async function () {
  this.parameters.accessToken = await getAccessToken(this.parameters.oauth) 
});

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