Skip to content

Latest commit

 

History

History
101 lines (75 loc) · 2.97 KB

parallel.md

File metadata and controls

101 lines (75 loc) · 2.97 KB

Parallel

Cucumber supports running scenarios in parallel. The main process becomes a "coordinator" and spins up several separate Node.js processes to be the "workers". You can enable this with the parallel configuration option:

  • In a configuration file { parallel: 3 }
  • On the CLI cucumber-js --parallel 3

The number you provide is the number of workers that will run scenarios in parallel.

Each worker receives the following env variables (as well as a copy of process.env from the coordinator process):

  • CUCUMBER_PARALLEL - set to 'true'
  • CUCUMBER_TOTAL_WORKERS - set to the number of workers
  • CUCUMBER_WORKER_ID - ID for worker ('0', '1', '2', etc.)

Timing

When using parallel mode, the last line of the summary output differentiates between real time elapsed during the test run and aggregate time spent actually running steps:

73 scenarios (73 passed)
512 steps (512 passed)
0m51.627s (executing steps: 4m51.228s)

Hooks

When using parallel mode, any BeforeAll and AfterAll hooks you have defined will run once per worker.

Custom work assignment

If you would like to prevent specific sets of scenarios from running in parallel you can use setParallelCanAssign.

Example:

setParallelCanAssign(function (pickleInQuestion, picklesInProgress) {
  // Only one pickle with the word example in the name can run at a time
  if (pickleInQuestion.name.includes('example')) {
    return picklesInProgress.every((p) => !p.name.includes('example'))
  }
  // No other restrictions
  return true
})

For convenience, the following helpers exist to build a canAssignFn:

import {
  setParallelCanAssign,
  parallelCanAssignHelpers,
} from '@cucumber/cucumber'

const { atMostOnePicklePerTag } = parallelCanAssignHelpers
const myTagRule = atMostOnePicklePerTag(['@tag1', '@tag2'])

// Only one pickle with @tag1 can run at a time
//   AND only one pickle with @tag2 can run at a time
setParallelCanAssign(myTagRule)

// If you want to join a tag rule with other rules you can compose them like so:
const myCustomRule = function (pickleInQuestion, picklesInProgress) {
  // ...
}

setParallelCanAssign(function (pickleInQuestion, picklesInProgress) {
  return (
    myCustomRule(pickleInQuestion, picklesInProgress) &&
    myTagRule(pickleInQuestion, picklesInProgress)
  )
})

Formatting

You can access workerId property in testCaseStarted envelope object:

const { Formatter } = require('@cucumber/cucumber')

class ExampleFormatter extends Formatter {
  constructor(options) {
    options.eventBroadcaster.on('envelope', (envelope) => {
      if (envelope.testCaseStarted) {
        if (envelope.testCaseStarted.workerId) {
          console.log(
            `the event has been fired from a worker with id ${envelope.testCaseStarted.workerId}`
          )
        } else {
          console.log('the event has been sent from the main thread')
        }
      }
    })

    super(options)
  }
}

module.exports = ExampleFormatter