How to implement Istanbul Coverage with Selenium and Mocha

Viewed 463

I am using Selenium with Mocha to run my Application tests and I would like to generate the code coverage as well.

I'm trying to add Istanbul to generate it however I think there are some points I didn't get and I don't really know from where should I start. Like the istanbul-instrumenter-loader module which I don't know if I need in my case ?

Running mocha will open the App on a port let's say 8081 (or even the deployed version) using the webdriver. (I don't think there is much work to do in the main folder - see the project structure below).

Now, under the Application/tests/uiTests folder, I want to initialize the directory of my code which is Application/components.

I tried using cwd in the nyc configuration, it didn't work obviously and I guess Istanbul does not see any file since everything is just zero in the displayed result.

Note : There is no webpack file under tests/uiTests

This is what I tried in .nycrc.json

{
    "extends": "@istanbuljs/nyc-config-typescript", // Since I'm using TS in both App and Tests
    "all": true,
    "extension": ["tsx"],
    "cwd" : "../../components"
}

This is how my project looks like

-- Application (main folder)
-- package.json
-- webpack.config.json

---- components (=> src)
------ **/*.tsx

---- Tests
------ uiTests <--- you can run mocha here
-------- package.json
-------- .mocharc.json
-------- tsconfig.json
-------- babel.config.js

.mocharc.json

{
  "extension": ["ts"],
  "spec": "core/**/*.spec.ts",
  "require": "config/register.ts",
  "timeout": 30000,
  "color": true,
  "reporter": "mocha-junit-reporter",
  "reporterOptions": {
    "mochaFile": "./report/results.xml"
  }
}

register.ts

require('core-js/stable');
require('regenerator-runtime/runtime');
require('chromedriver');
require('ts-node/register/transpile-only');
require('source-map-support/register');
const register = require('@babel/register').default;

register({ extensions: ['.ts', '.tsx', '.js', '.jsx'] });

babel.config.js

module.exports = (api) => {
    // Cache configuration is a required option
    api.cache(false);

    const presets = [
        '@babel/preset-typescript',
        '@babel/preset-env',
    ];

    return { presets, sourceType: 'module' };
};

uiTests/package.json

{
  "...": "...",
  "scripts": {
    "test": "mocha",
    "coverage": "tsc && nyc mocha"
  },
  "directories": {
    "test": "./core"
  },
  "devDependencies": {
    "@babel/core": "7.14.0",
    "@babel/preset-env": "7.14.1",
    "@babel/preset-typescript": "7.13.0",
    "@babel/register": "7.13.16",
    "@istanbuljs/nyc-config-typescript": "^1.0.1",
    "@types/assert": "1.5.4",
    "@types/chai": "4.2.18",
    "@types/chromedriver": "81.0.0",
    "@types/mocha": "8.2.2",
    "@types/selenium-webdriver": "4.0.12",
    "@typescript-eslint/eslint-plugin": "4.22.1",
    "@typescript-eslint/parser": "4.22.1",
    "assert": "2.0.0",
    "chai": "4.3.4",
    "chromedriver": "91.0.0",
    "core-js": "3.12.1",
    "eslint": "7.26.0",
    "eslint-plugin-jsdoc": "33.3.0",
    "eslint-plugin-prefer-arrow": "1.2.3",
    "mocha": "8.4.0",
    "mocha-junit-reporter": "2.0.0",
    "nyc": "^15.1.0",
    "regenerator-runtime": "0.13.7",
    "selenium-webdriver": "4.0.0-beta.1",
    "source-map-support": "^0.5.19",
    "ts-node": "^9.1.1",
    "typescript": "4.2.4"
  },
  "...": "...",
}

1 Answers

Getting istanbul working

I had the same problem you had months ago. All zeroes in the reports. The problem has to do with the use of ESM modules. It appears that may be your issue too: I see sourceType: 'module' in your babel config.

If so, you will need to uses @istanbuljs/esm-loader-hook to get mocha to work with Istanbul when using modules.

Install @istanbuljs/esm-loader-hook and then invoke mocha like this:

npx nyc mocha --experimental-loader=@istanbuljs/esm-loader-hook

You can see https://github.com/istanbuljs/nyc/issues/1343 for some troubleshooting steps.

A possibly better alternative: c8

If you still have trouble getting Istanbul to work, before you spend too much time trying to figure out why, I strongly recommend you try an alternative to istanbul/nyc that uses V8's native coverage facilities and just magically works: c8.

It is written by @bcoe, one of the maintainers of nyc/instanbul. When I had trouble with Istanbul, it took me 5 minutes to get c8 to work. It is compatible with Istanbul's reporters and you get the exact same reporting functionality out-of-the-box.

Related