Search code examples
javascriptnode.jsmocha.jsistanbulnyc

Error getting the coverage report with rewire / cross-env


I'm trying to get the coverage report using nyc and it works well if I'm not using the cross-env plugin.

cross-env NODE_ENV=test nyc mocha --ui bdd --reporter spec --colors --require babel-core/register tests --recursive

executing this command the code coverage won't run properly and the result is the following:

 31 passing (1s)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |        0 |        0 |        0 |        0 |                   |
----------|----------|----------|----------|----------|-------------------|

However if I run this nyc mocha --ui bdd --reporter spec --colors --require babel-core/register tests --recursive it will work as expected.

---------------------|----------|----------|----------|----------|-------------------|
File                 |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------------|----------|----------|----------|----------|-------------------|
All files            |    79.45 |    64.29 |    35.71 |    84.62 |                   |
 constants           |      100 |      100 |      100 |      100 |                   |
  index.js           |      100 |      100 |      100 |      100 |                   |
 db                  |    77.05 |    64.29 |    33.33 |    83.02 |                   |
---------------------|----------|----------|----------|----------|-------------------|

The issue is that I need to set the env variable in order to use the rewire plugin that allows me to run the test properly (indeed, most of the test are failing because of that).

This is my .bebelrc

{
  "presets": ["es2015"],
  "env": {
    "test": {
      "plugins": ["istanbul", "babel-plugin-rewire"]
    }
  }
}

note: I think the issue is related to the babel-plugin-rewire. Indeed, even removing the cross-env and placing the plugins collection in the root will give me the same empty coverage result.


Solution

  • I've found a solution on this issue playing around the babel configuration file and the plugins. To avoid this case would be better to use the last env preset. I also created a repo that reproduce the error and has a readme similar to this post.

    With rewire/cross-env

    Running the test using the default commands (that use rewire and cross-env) will generate an empty coverage report:

    npm run test
    

    this command will execute only the tests and both of them will pass

    npm run test:cov
    

    this will execute the previous test script but will add the coverage report, which will result empty

    ----------|----------|----------|----------|----------|-------------------|
    File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    ----------|----------|----------|----------|----------|-------------------|
    All files |        0 |        0 |        0 |        0 |                   |
    ----------|----------|----------|----------|----------|-------------------|
    

    Without rewire/cross-env

    removing cross-env NODE_ENV=test from the test script will avoid to load rewire and will generate a correct coverage. The side effect is that the test that use the rewire will fail.

    npm run test2
    

    will run the script without cross-env, so babel will not load the rewire plugin and so one test will fail.

    npm run test:cov2
    

    this command will use the previous test2 script and generate the coverage. In this case the coverage report will be generated correctly.

    ------------------|----------|----------|----------|----------|-------------------|
    File              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    ------------------|----------|----------|----------|----------|-------------------|
    All files         |    64.29 |      100 |    54.55 |    66.67 |                   |
     src              |       75 |      100 |       60 |    85.71 |                   |
      a-dependency.js |      100 |      100 |      100 |      100 |                   |
      a-module.js     |       60 |      100 |        0 |       75 |                 6 |
     tests            |       60 |      100 |       50 |       60 |                   |
      test.js         |       60 |      100 |       50 |       60 |... 23,24,26,27,28 |
    ------------------|----------|----------|----------|----------|-------------------|
    

    but its not correct due the missing rewire plugin.

    babelrc (es2015)

    {
      "presets": ["es2015"],
      "env": {
        "test": {
          "plugins": ["istanbul", "rewire"]
        }
      }
    }
    

    this is the babel configuration file used in the solution. Removing rewire plugin from the plugin collection will generate and empty coverage with npm run test:cov but not with npm run test:cov2 (which is not using cross-env).

    If I modify the babelrc in this way

    {
      "presets": ["es2015"],
      "plugins": ["istanbul", "rewire"]
    }
    

    both npm run test:cov (with cross-env) and npm run test:cov2 (without cross-env). Will generate an empty result.

    If I remove both the plugins

    {
      "presets": ["es2015"]
    }
    

    both command (with and without cross-env) will generate a coverage result (partial, since one test will fail)

    Removing only istanbul from the plugin collection will generate a full coverage file and this would be the result (as expected)

    ------------------|----------|----------|----------|----------|-------------------|
    File              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    ------------------|----------|----------|----------|----------|-------------------|
    All files         |      100 |      100 |      100 |      100 |                   |
     src              |      100 |      100 |      100 |      100 |                   |
      a-dependency.js |      100 |      100 |      100 |      100 |                   |
      a-module.js     |      100 |      100 |      100 |      100 |                   |
     tests            |      100 |      100 |      100 |      100 |                   |
      test.js         |      100 |      100 |      100 |      100 |                   |
    ------------------|----------|----------|----------|----------|-------------------|
    

    babelrc (env)

    After going across this issues around the previous es2015 preset, I moved to the env one. Installing it with npm install babel-preset-env --save-dev then I've modified my babelrc in this way.

    {
      "presets": [
        ["env", {
          "targets": {
            "node": "current"
          }
        }]
      ],
      "env": {
        "test": {
          "plugins": ["istanbul", "rewire"]
        }
      }
    }
    

    In this case npm run test works properly and npm run test:cov will generate a correct coverage report. And there will be no issue with cross-end or rewire.

    conclusion

    Somehow both rewire and cross-env are creating issue if combined with babel when using the es2015 preset. To generate the report with this preset apparenttly is sufficient to remove istanbul from the babel plugins and use only rewire (it will work well also with cross-env in this case).

    I rather suggest to upgrate to the env preset and use the babel plugins as suggested (unless it create other issue to your project)

    env

    > node --version
    v9.4.0
    > npm --version
    5.6.0
    >ver
    Microsoft Windows [Version 10.0.16299.309]
    

    Same behavior has been observed on MacOS