DEV Community

Benjamin E. Coe
Benjamin E. Coe

Posted on

7 3

Enforce JavaScript Code Coverage with GitHub Actions

I recently migrated a few open-source projects over to GitHub actions for continuous-integration. In the process, I came up with a neat trick that I thought was worth sharing...

nyc's --check-coverage flag

The JavaScript coverage libraries c8 and nyc expose the flag --check-coverage. Used in conjunction with --lines, --branches, --functions, and --statements, --check-coverage will exit with an error if coverage falls below the threshold specified.

c8 is a tool inspired by nyc that uses V8's built-in test coverage, see: Rethinking JavaScript Test Coverage.

As an example,

c8 --check-coverage --lines=95 npm run test

when run on a program with less than 95% line coverage, exits with the following error:

ERROR: Coverage for lines (92%) does not meet global threshold (95%)

Adding thresholds to .nycrc

Thresholds can be specified in the .nycrc configuration file, which is read automatically by c8 and nyc.

Here's an example of the configuration file from yargs:

{
  "reporter": [
    "html",
    "text"
  ],
  "lines": 100,
  "branches": "96",
  "statements": "100"
}

The thresholds in this file can then be treated like a ratchet, i.e., as coverage increases on your project, increase the value of lines, branches, and statements accordingly.

Adding a coverage job to a workflow

Once thresholds are set in a project's configuration, it's easy to add an additional job to a continuous integration workflow that fails if coverage drops below the thresholds.

Here's an example of a coverage job that was added to yargs' ci.yaml workflow:

on:
  push:
    branches:
      - master
  pull_request:
name: ci
jobs:
  ...
  coverage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: actions/setup-node@v1
        with:
          node-version: 13
      - run: npm install
      - run: npm test
      - run: npm run coverage

npm run coverage corresponds to the following npm script:

{
  ...
  "scripts": {
    "coverage": "c8 report --check-coverage"
  }
}

c8 reads the thresholds from .nycrc and exits with 1 if the specified thresholds are not met, failing the workflow's job.

But what about my badges?!

You're probably asking, "this is all well and good, but how can I add a badge to the top of my README"?

Good news, support for a .nycrc coverage badge was just added to shields.io.

see: https://github.com/badges/shields/pull/4759

shields.io


Services like codecov.io and coveralls.io are awesome: providing coverage report merging, beautiful visualizations, historical data, etc.

If you're not feeling you need these features just yet, but would like to enforce coverage on your JavaScript project, consider using c8 or nyc with the --check-coverage flag in a GitHub Action workflow.

AWS Q Developer image

Your AI Code Assistant

Ask anything about your entire project, code and get answers and even architecture diagrams. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Start free in your IDE

Top comments (1)

Collapse
 
tunnckocore profile image
Charlike Mike Reagent

Oh please don't promote Coveralls. I even want to puke when I see it in package.json, even more when in npm scripts :D

Codecov is the name of the game. Single line of 20 bytes, period. No tokens, no setup, no "add", no bullshits.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay