In Cypress, if any test case fails out of automation suite - posttest section in package.json is not executed

Viewed 1882

Whenever I am executing the whole Cypress suite from the command line to execute a specific folder, when a test case fails during the suite execution the "posttest" section in the package.json file is not executed . Throws following error.

error Command failed with exit code 3.

In package.json file the script section is as follows

"scripts": {
    "pretest": "yarn run [some command]",
    "chrome": "yarn run cypress run --browser chrome",
    "cypress:open": "cypress open",
    "combine-reports": "mochawesome-merge --reportDir cypress\\reports\\mocha > cypress\\reports\\mochareports\\report.json",
    "generate-report": "marge cypress\\reports\\mochareports\\report.json -f report -o cypress\\reports\\mochareports",
    "report:copyScreenshots": "Xcopy cypress\\screenshots cypress\\reports\\mochareports\\screenshots /E/H/C/I",
    "test": "cypress run",
    "posttest": "yarn run report:copyScreenshots && yarn run combine-reports && yarn run generate-report"
  }

Command executed for command line :

yarn run test --spec "cypress/integration/Demo1/*" --browser chrome
2 Answers

You might want to use the Cypress Module API to invoke cypress run and control the exit code.

This is my script which differs from the docs example slightly,

/scripts/cy-run.js

const cypress = require('cypress')

const args = process.argv.slice(2);
const options = ['cypress', 'run', ...args]; // saves passing 'cypress run' on the command line

cypress.cli.parseRunArguments(options).then(runOptions => {

  console.log('runOptions', runOptions)

  cypress.run(runOptions).then(() => {

    process.exit(0);   // control the exit code 

  }).catch(error => {
    console.error(error);
  })
}).catch(error => {
  console.error(error)
})

package.json

{
  ...
  "scripts": {
    "cyrun": "node scripts/cy-run.js",
    "postcyrun": "echo next command",

sample test

it('succeeds', () => {
  expect(1+1).to.equal(2)
})

it('fails', () => {
  expect(1+1).to.equal(3)
})

command line

yarn cyrun --spec "**/test.spec.js" --browser chrome

console output

node scripts/cy-run.js --spec **/test.spec.js --browser chrome
runOptions { browser: 'chrome', spec: '**/test.spec.js' }


==================================================================================================

  (Run Starting)

  ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
  │ Cypress:    5.5.0                                                                            │
  │ Browser:    Chrome 86                                                                        │
  │ Specs:      1 found (test.spec.js)                                                           │
  │ Searched:   **\test.spec.js                                                                  │
  └──────────────────────────────────────────────────────────────────────────────────────────────┘

... test details

==================================================================================================

  (Run Finished)


       Spec                                              Tests  Passing  Failing  Pending  Skipped
  ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
  │ ×  test.spec.js                           820ms        2        1        1        -        - │
  └──────────────────────────────────────────────────────────────────────────────────────────────┘
    ×  1 of 1 failed (100%)                   820ms        2        1        1        -        -

$ echo next command
next command          // postcyrun is running
Done in 14.35s.

When you use pre- and post-task scripts in your package file:

  "scripts": {
    "pre<task>": "...",
    "<task>": "...",
    "post<task>": "...",
    ...
  }

running yarn task (or npm run task) is effectively yarn pre<task> && yarn <task> && yarn post<task> - if any of those steps fails, exits non-zero, the later steps don't run at all.

One pattern I've used to ensure any clean-up happens is the following:

  "scripts": {
    "pre<task>": "...",
    "<task>": "... || (yarn post<task> && exit 1)",
    "post<task>": "...",
    ...
  }

For example here you can see where I've used this to ensure that the containers are stopped whether or not the tests fail.

However, note that this will cause issues if you try to pass arguments, e.g. yarn <task> --foo 'bar', because, although they are only passed to <task> not the pre- and post- scripts, there is no way to target the arguments to the ... part rather than the whole command.

Related