Jest: Global and single file coverage thresholds

Created on 30 Jan 2018  路  11Comments  路  Source: facebook/jest

Do you want to request a _feature_ or report a _bug_?

Feature

What is the current behavior?

Currently, when using both global and path/glob thresholds, the global config combines the coverage for remaining files only (as documented).

What is the expected behavior?

I'll describe my use case. A global threshold is configured as following:

coverageThreshold: {
  global: {
    statements: 85,
    branches: 80,
    functions: 85,
    lines: 85
  }
}

This makes it possible to commit completely untested files as long as the overall coverage is fulfilled. To solve this issue I would like to enforce every file being tested for at least 50%:

coverageThreshold: {
  global: {
    statements: 85,
    branches: 80,
    functions: 85,
    lines: 85
  },

  "app/**/*.js": {
    statements: 50,
    branches: 50,
    functions: 50,
    lines: 50
  }
}

However, this won't work as expected. First, running this config will fail if app/ and global point to the same files (which is expected as "If the file specified by path is not found, error is returned."). Second, now the global threshold is overruled by the "local" threshold.

It would be great to have an option to use a global threshold which always applies to all files in addition to glob/path thresholds for single file thresholds.

Please provide your exact Jest configuration and mention your Jest, node,
yarn/npm version and operating system.

Windows 7
jest v22.1.4
node v8.9.1
npm v5.6.0

Needs Triage

Most helpful comment

@averath
Because what we need is to have _both_ checks in place, e.g.:

a) The _total_ coverage should be at least 90%
b) The _per-file_ coverage should be at least 50%

In other words, it's okay if a single file does not meet the 90% coverage (as long as the overall coverage is at least 90%), but it's not okay if a single file has no coverage at all.

All 11 comments

@darekkay do you have a repro of that?

ping @darekkay

Sorry for my late response @thymikee , here it is: jest-coverage.

I noticed some differences between jest versions:

In [email protected] it works as expected:

$ jest --coverage
...
------------|----------|----------|----------|----------|----------------|
File        |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines |
------------|----------|----------|----------|----------|----------------|
All files   |       80 |      100 |       80 |       80 |                |
 product.js |        0 |      100 |        0 |        0 |            4,7 |
 sum-01.js  |      100 |      100 |      100 |      100 |                |
 sum-02.js  |      100 |      100 |      100 |      100 |                |
 sum-03.js  |      100 |      100 |      100 |      100 |                |
 sum-04.js  |      100 |      100 |      100 |      100 |                |
------------|----------|----------|----------|----------|----------------|
Jest: Coverage for statements (0%) does not meet C:\jest-coverage\app\product.js threshold (50%)
Jest: Coverage for lines (0%) does not meet C:\jest-coverage\app\product.js threshold (50%)
Jest: Coverage for functions (0%) does not meet C:\jest-coverage\app\product.js threshold (50%)

In [email protected] we get this instead:

$ jest --coverage
...
------------|----------|----------|----------|----------|-------------------|
File        |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------|----------|----------|----------|----------|-------------------|
All files   |       80 |      100 |       80 |       80 |                   |
 product.js |        0 |      100 |        0 |        0 |               2,5 |
 sum-01.js  |      100 |      100 |      100 |      100 |                   |
 sum-02.js  |      100 |      100 |      100 |      100 |                   |
 sum-03.js  |      100 |      100 |      100 |      100 |                   |
 sum-04.js  |      100 |      100 |      100 |      100 |                   |
------------|----------|----------|----------|----------|-------------------|
Jest: Coverage data for global was not found.
Jest: "C:\jest-coverage\app\product.js" coverage threshold for statements (50%) not met: 0%
Jest: "C:\jest-coverage\app\product.js" coverage threshold for lines (50%) not met: 0%
Jest: "C:\jest-coverage\app\product.js" coverage threshold for functions (50%) not met: 0%

We get Coverage data for global was not found (which, again, is expected as "If the file specified by path is not found, error is returned."). To demontrate the issue a little better, we can delete product.js to get a 100% coverage, which will still cause npm run test to fail:

$ jest --coverage
...
-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 sum-01.js |      100 |      100 |      100 |      100 |                   |
 sum-02.js |      100 |      100 |      100 |      100 |                   |
 sum-03.js |      100 |      100 |      100 |      100 |                   |
 sum-04.js |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Jest: Coverage data for global was not found.

I was doing some coverage testing in the gatsby repo and found that calculated global coverage differs when there are files or other folders included included.

i.e

coverageThreshold: {
    global: {
      lines: 42,
      statements: 43,
      functions: 40,
      branches: 42,
    },
  },

This would pass the test, but

coverageThreshold: {
    global: {
      lines: 42,
      statements: 43,
      functions: 40,
      branches: 42,
    },
     "packages/babel-plugin-remove-graphql-queries/src/": { ...coreThresholds },
     "packages/gatsby/src/": { ...coreThresholds },
     "packages/gatsby-plugin-page-creator/src/": { ...coreThresholds },
     "packages/gatsby-image/src/": { ...coreThresholds },
     "packages/gatsby-link/src/": { ...coreThresholds },
     "packages/gatsby-plugin-sharp/src/": { ...coreThresholds },
  },

fails the build because global thresholds dropped to 38.

Any updates?

I think the next step is to for someone interested to submit a PR

I would also appreciate the global coverage not to be contaminated by the more specific file or folder coverages...

Why don't you just add:

coverageThreshold: {
    "**/*": {
      "branches": 90,
      "functions": 90,
      "lines": 90,
      "statements": 90
    }
  }

@averath
Because what we need is to have _both_ checks in place, e.g.:

a) The _total_ coverage should be at least 90%
b) The _per-file_ coverage should be at least 50%

In other words, it's okay if a single file does not meet the 90% coverage (as long as the overall coverage is at least 90%), but it's not okay if a single file has no coverage at all.

I was doing some coverage testing in the gatsby repo and found that calculated global coverage differs when there are files or other folders included included.

i.e

coverageThreshold: {
    global: {
      lines: 42,
      statements: 43,
      functions: 40,
      branches: 42,
    },
  },

This would pass the test, but

coverageThreshold: {
    global: {
      lines: 42,
      statements: 43,
      functions: 40,
      branches: 42,
    },
     "packages/babel-plugin-remove-graphql-queries/src/": { ...coreThresholds },
     "packages/gatsby/src/": { ...coreThresholds },
     "packages/gatsby-plugin-page-creator/src/": { ...coreThresholds },
     "packages/gatsby-image/src/": { ...coreThresholds },
     "packages/gatsby-link/src/": { ...coreThresholds },
     "packages/gatsby-plugin-sharp/src/": { ...coreThresholds },
  },

fails the build because global thresholds dropped to 38.

does that worked for you after that?
I am also tring something similar but it doesn't work for me.

I have a similar requirement and I did a workaround by chaining commands together and using the coverageThreshold CLI option (which isn't formally documented)

In my package.json:

scripts: {
   ...
   "test": "jest"
   "test:coverage": "npm run test -- --coverage --coverageThreshold='{\"app/**/*.js\":{\"statements\":\"50\"}}' && npm run test -- --coverage --coverageThreshold='{\"global\":{\"statements\":\"80\"}}'"
}
   ...

I will run npm run test:coverage. The first chained command will ensure that individual files committed must have at least 50% code coverage in statements while the second chained command will check that all files in the project must have at least 80% code coverage in statements

Was this page helpful?
0 / 5 - 0 ratings