'How do I automatically check for '.only' calls accidentally left in Mocha specs?

I occasionally forget to remove .only calls from my Mocha specs before pushing spec changes. Doing so obviously affects test coverage, which requires addressing the failure(s). I'd like to catch these before I push changes, ideally as part of the linting process with ESLint and with minimal effort.



Solution 1:[1]

You're looking for the mocha/no-exclusive-tests rule, part of the eslint-plugin-mocha plugin. It fails if it finds any describe.only or it.only. Very useful!

From the docs:

This plugin requires ESLint 4.0.0 or later.

npm install --save-dev eslint-plugin-mocha

Then add a reference to this plugin and selected rules in your eslint config:

{
  "plugins": [
    "mocha"
  ],
  "rules": {
    "mocha/no-exclusive-tests": "error"
  }
}

There is also a mocha/no-skipped-tests if you want to prevent it.skip or xit from being committed too. However, I find that .skip is sometimes valid, so I find it best to just prevent .only.

That plugin also has a ton of other useful checks, so be sure to read their docs!

Solution 2:[2]

You have a --forbid-only parameter to be passed when executing mocha which will make your tests fail.

You have also the --forbid-pending.

Here from the official doc:

--forbid-only causes test marked with only to fail the suite

--forbid-pending causes pending tests and test marked with skip to fail the suite

Solution 3:[3]

My solution was to use a simple bash script with the grep command, added to the package.json scripts section like so:

"scripts": {
  "lint:only": "RESULT=\"$(grep -rHn '[.]only\\|[.]skip' spec/ --color=always)\"; if [ -n \"$RESULT\" ]; then printf \"Oops! You left a few things in your specs! \n\n${RESULT}\n\n\"; fi",
  "lint": "eslint --ext js src config scripts bin config server; yarn lint:only"
  ...
}

In a nutshell, this checks the spec/ directory for anything matching .only or .skip and outputs the filename + line if anything offending is found. Color is added for clarity and the script is run as part of linting with ESLint and Yarn.

Solution 4:[4]

Another package doing just this is eslint-plugin-no-only-tests.

Alternatively, this can now be done by following built-in ESLint rules, but they will highlight the whole function body of the callback as error as well:

"no-restricted-syntax": [
  "error",
  {
    "selector": "CallExpression[callee.object.type='Identifier'][callee.object.name='it'][callee.property.type='Identifier'][callee.property.name='only']",
    "message": "Do not commit it.only. Use it instead."
  },
  {
    "selector": "CallExpression[callee.object.type='Identifier'][callee.object.name='describe'][callee.property.type='Identifier'][callee.property.name='only']",
    "message": "Do not commit describe.only. Use describe instead."
  }
]

For an exclusion of fdescribe and fit the following can be used:

"no-restricted-globals": [
  "error",
  {
    "name": "fdescribe",
    "message": "Do not commit fdescribe. Use describe instead."
  },
  {
    "name": "fit",
    "message": "Do not commit fit. Use it instead."
  },
]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Community
Solution 3 user3006381
Solution 4 Rene Hamburger