Test coverage in Deno with Codecov and GitHub Actions

Test coverage in Deno with Codecov and GitHub Actions

In Deno 1.4 a new flag --coverage for deno test was added to collect test coverage. In Deno 1.8 support for lcov format was shipped, meaning that we can now easily setup coverage report services. In this tutorial I will show how to configure Codecov and Github Actions for online coverage report.

# Writing tests

Deno provides a convinient built-in API for writing tests. It also has a special standard module for testing that includes assertion functions and benchmarking.

Let’s write a simple test:

// sum_test.ts
import { assertEquals } from 'https://deno.land/[email protected]/testing/asserts.ts'
import { sum } from './sum.ts'

Deno.test({
  name: 'sum(a + b)',
  fn: () => {
    assertEquals(sum(2, 3), 5)
  },
})

If you are used to Jest-like testing you might try Wizard:

// sum_test.ts
import { sum } from './sum.ts'
import { describe, it, expect, run } from 'https://deno.land/x/wizard/mod.ts'

describe('A test suite', () => {
  it('should sum a + b', () => {
    expect(sum(2, 3)).toBe(5)
  })
})

run() // Start test runner

To run the test type this in the terminal:

deno test

# Generating coverage

To produce the coverage files from tests you need to use --coverage and --unstable (because it is still an experimental feature) flags for the deno test command:

deno test --unstable --coverage=coverage

This will create a set of coverage files in the coverage folder. You can pick any folder as the coverage output by specicyfing it with the --coverage flag.

Next, we need to generate a coverage report so services like Codecov will be able to consume it:

deno --unstable coverage ./coverage --lcov > coverage.lcov

After running the command a new file “coverage.lcov” will get created.

We created the coverage locally but it doesn’t get uploaded anywhere for now.

# Codecov

For online coverage report we will use Codecov. Sign up there and open the URL with your repository address:

https://app.codecov.io/gh/<user>/<repo>

Later Codecov will know that this repo has been initiated before for coverage upload.

# GitHub Actions

As the CI I’ll be using GitHub Actions because it already has a premade Deno action and is easy to configure.

The config looks something like this:

name: CI

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: denolib/setup-deno@v2
        with:
          deno-version: v1.8
      - name: Create coverage files
        run: deno test --unstable --coverage=coverage # create coverage files
      - name: Create coverage report
        run: deno --unstable coverage ./coverage --lcov > coverage.lcov # create coverage report
      - name: Collect coverage
        uses: codecov/[email protected] # upload the report on Codecov
        with:
          file: ./coverage.lcov

Create a file called ci.yml or main.yml with these contents and put it in the .github/workflows folder in your repository. This will trigger GitHub to use their CI.

After pushing that file Github Actions will start running.

Congrats! Now you have continious test run and coverage report.

# Badges

For convinience you may also add badges as indicators:

<!-- GitHub Actions -->

[![](https://img.shields.io/github/workflow/status/<user>/<repo>/CI?style=flat-square)](https://github.com/<user>/<repo>/actions)

<!-- Codecov -->

[![](https://img.shields.io/codecov/c/gh/<user>/<repo>?style=flat-square)](https://codecov.io/gh/<user>/<repo>)

# Conclusion

Despite that coverage tooling in Deno is relatively new, it’s already possible to set the full toolchain up with no hassle. Notice that it’s all done by the Deno CLI commands, unlike Node, where you have to (at least) install c8 and uvu for tests and coverage report.