Cucumber.js

repository·main·Indexed 26 days ago

https://github.com/cucumber/cucumber-js

The official JavaScript implementation of Cucumber for Node.js. It allows for running automated tests written in plain language (Gherkin) to facilitate collaboration between technical and non-technical team members. Features include a CLI (cucumber-js), support for multiple configuration formats (JSON, YAML, JS, TS), and APIs for creating custom formatters and snippet syntaxes.

Tokens
33.6K
Snippets
80
Records
215
Agent score
89%

What's inside @cucumber/cucumber

  1. Use built-in Cucumber formatters

    main

    Cucumber-js provides several built-in formatters to control how test results are displayed or exported. You can choose a formatter based on whether you need real-time terminal feedback, a rich interactive report, or structured data for other tools.

    Available built-in formatters:

    • summary: Outputs a summary of results (including errors and pending step snippets) at the end of the run.
    • progress: Provides real-time feedback for each step/hook and a summary at the end.
    • progress-bar: Provides a real-time updating progress bar.
    • pretty: Writes a rich, detailed report of scenario and example execution as it happens (Added in v12.1.0; can be referenced as @cucumber/pretty-formatter from v11.1.0).
    • html: Produces a standalone, interactive HTML report.
    • message: Outputs Cucumber Messages as newline-delimited JSON (recommended for structured data).
    • json: Outputs results in the legacy JSON format (maintenance mode).
    • junit: Produces XML-based reports in the JUnit format, ideal for CI platforms.
    • snippets: Prints only the code snippets needed to implement undefined steps.
    • usage: Lists step definitions, their usage locations, and durations.
    • usage-json: Outputs step usage data in JSON format.
  2. Combine sharding and parallel execution

    main

    Sharding and Parallel execution are distinct features that can be used together:

    • Sharding: Splits execution across independent processes or different machines (e.g., multiple CI jobs).
    • Parallel: Runs scenarios in parallel within a single test run (using multiple cores on a single machine).

    You can combine them to split tests across multiple machines (sharding) and then use multiple cores on each of those machines (parallel) to maximize throughput.

  3. Configure Cucumber using TypeScript

    main

    You can use TypeScript for your configuration files with .ts, .mts, or .cts extensions. These are loaded using Node.js built-in TypeScript support.

    Caveats:

    • Your tsconfig.json will not be honored.
    • You must be explicit about type imports.

    Use the IConfiguration type from @cucumber/cucumber for type safety.

    import type { IConfiguration } from '@cucumber/cucumber'
    
    export default {
      parallel: 2,
      format: ['html:cucumber-report.html']
    } satisfies Partial<IConfiguration>
  4. Enable the rerun formatter

    main
    To use the rerun workflow, you must enable the rerun formatter during every test execution. This generates a file containing the locations of failed scenarios. The output filename must start with the @ character (e.g., @rerun.txt) so cucumber-js can distinguish it from feature files. It is recommended to add this file to your .gitignore.
  5. Attach text, images, and binary data to test outputs

    main

    You can add attachments to the output of messages and JSON formatters using the this.attach method. The default world constructor assigns this function to this.attach. If you use a custom world constructor, you must manually assign the attach function passed to the constructor to this.attach to enable this feature.

    Text Attachments

    By default, text is saved as text/plain. You can specify a different MIME type using an options object.

    File Names

    You can provide a fileName in the options object to allow formatters to make the attachment available for download.

    Binary Data (Images, Buffers, Streams)

    • Streams: You can pass a stream.Readable. You must either await the returned promise or provide a callback to ensure the stream is fully read before continuing.
    • Buffers: You can pass a Node.js Buffer directly.
    • Base64 Strings: If you have a pre-encoded base64 string, prefix the mediaType with base64: (e.g., base64:image/png).
    var {After, Status} = require('@cucumber/cucumber');
    
    // Attach text with custom MIME type and filename
    After(function () {
      this.attach('{"name": "some JSON"}', {
        mediaType: 'application/json',
        fileName: 'results.json'
      });
    });
    
    // Attach a stream (using await)
    After(async function (testCase) {
      if (testCase.result.status === Status.FAILED) {
        var stream = getScreenshotOfError();
        await this.attach(stream, { mediaType: 'image/png' });
      }
    });
    
    // Attach a Buffer
    After(function (testCase) {
      if (testCase.result.status === Status.FAILED) {
        var buffer = getScreenshotOfError();
        this.attach(buffer, { mediaType: 'image/png' });
      }
    });
    
    // Attach a base64-encoded string
    After(async function (testCase) {
      if (testCase.result.status === Status.FAILED) {
        const screenshot = await driver.takeScreenshot();
        this.attach(screenshot, { mediaType: 'base64:image/png' });
      }
    });
  6. Enable parallel execution

    main
    Cucumber can run scenarios in parallel by using a coordinator process that manages multiple worker threads. You can enable this using the parallel configuration option via a configuration file or the CLI. The value provided determines the number of workers that will run scenarios in parallel.
  7. Use Hooks for setup and teardown

    main

    Hooks allow you to execute code before or after scenarios and steps.

    • Before hooks execute in the order they were defined.
    • After hooks execute in the reverse order they were defined.

    Important: Do not use arrow functions for hooks if you need to access the World instance via this. Use standard function expressions instead.

    Hooks can be synchronous, use an asynchronous callback, or return a Promise.

    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();
    });
  8. Understand the Cucumber.js deprecation lifecycle

    main

    Cucumber.js follows a controlled deprecation process to minimize disruption when removing functionality:

    1. Minor Version (N.x.x): A @deprecated comment is added to code/types, and a runtime warning is issued when the functionality is invoked.
    2. Major Version (N+1.0.0): The deprecation is highlighted in the release notes.
    3. Major Version (N+2.0.0): The deprecated functionality is removed (though this timeline may be extended if the ecosystem requires more time).
  9. Configure Cucumber using configuration files

    main

    Cucumber can be configured using a file located in your project root. It will automatically use the first one it finds from the following supported formats:

    • cucumber.json
    • cucumber.yaml
    • cucumber.yml
    • cucumber.js
    • cucumber.cjs
    • cucumber.mjs

    To use a configuration file located in a non-standard location, use the --config CLI option.

    Note: Configuration settings should typically be placed within a default property to support Profiles.

    cucumber-js --config config/cucumber.json