🔍

Jestのカバレッジをお手軽にチェックする

2021/09/13に公開

結論

  • Jestは実行時に--coverageReporters=json-summaryオプションをつけることでsummaryのjsonを出力してくれる
  • summaryのjsonからtotalのpercentを取得できる
  • totalのpercentを基に簡易的なカバレッジのしきい値チェックができる!

はじめに

ふと急に、circleci上でお手軽にカバレッジのしきい値チェックがしたくなった

circleciのドキュメントに書いてあるが、コードカバレッジ用に便利な機能が包括された良さげなサービスにお任せすればやりたいことはできそうだったが、Jestだけで気軽にできないかしらとオプション調べてたら良さげなオプションがあったので、このオプションを使って、しきい値チェックのscriptを作ることにした

記事のターゲット

  • Jestで簡単な[1]カバレッジのチェックがしたい人

環境

package.json
{
  "devDependencies": {
    "jest": "26.6.3",
    "ts-node": "10.2.1",
    "typescript": "4.4.3",
  }
}

カバレッジの結果をjsonに出力する

結論でも書きましたが、summaryの結果を出力するオプションを追加してJestを実行します

package.json
{
  "scripts": {
    "test-total-coverage": "jest --collectCoverage=true --coverageReporters=json-summary",
  }
}

デフォルトではcoverage/coverage-summary.jsonに出力されるはず

しきい値チェックのscriptを作る

  1. coverage/coverage-summary.jsonの読み込み
  2. チェックしたい項目の値を取得
  3. しきい値より低くないかチェックする
coverage-summary.jsonはこんな感じ
coverage/coverage-summary.json
{
  "total": {
    "lines":{
      "total":1480,
      "covered":413,
      "skipped":0,
      "pct":27.91
    },
    "statements":{
      "total":1566,
      "covered":423,
      "skipped":0,
      "pct":27.01
    },
    "functions":{
      "total":594,
      "covered":193,
      "skipped":0,
      "pct":32.49
    },
    "branches":{
      "total":763,
      "covered":171,
      "skipped":0,
      "pct":22.41
    }
  },
  // 以降、ディレクトリやファイルごとの値がつらつらと出力される
}

pctが低いことに気づいたそんな感の良い人はキライです

今回はFunctionsのパーセントが80%より下回ったらCIが落ちるように書いてみました(項目としきい値はテキトウです)

scripts/check-coverage/index.ts
import { readFileSync } from 'fs'

// 出力されるjsonを見て、型をお気持ち程度に定義
type CoverageColumn = {
  total: number
  covered: number
  skipped: number
  pct: number
}
type CoverageType = 'lines' | 'statements' | 'functions' | 'branches'
type CoverageValue = { [key in CoverageType]: CoverageColumn }
type Coverage = { [key: string]: CoverageValue }

const main = () => {
  try {
    // NOTE:(yota-hada) 今回はこのscriptをscripts/check-coverage/index.tsにおいたので、root直下からcoverage/coverage-summary.jsonにアクセスするために余分なpathを消してる
    const dirNames = __dirname.split('/')
    const filterNames = dirNames.filter(
      (dirName) => dirName !== 'scripts' && dirName !== 'check-coverage',
    )
    const dir = filterNames.join('/')

    const input = JSON.parse(
      readFileSync(`${dir}/coverage/coverage-summary.json`, 'utf-8'),
    ) as Coverage

    const functionCoverage = input.total.functions.pct
    // しきい値ってどれくらいが良いんでしょね
    const mustCoverage = 80

    if (functionCoverage < mustCoverage) {
      // HACK:(yota-hada) 別途カバレッジをcircleciのartifactsなどにアップロードしておき、詳細を確認できるようにしとくともっと良き
      const errMsg = 'テストのカバレッジ(Functions)が低すぎます。今すぐテストを書くのです'
      throw new Error(errMsg)
    }
  } catch (e) {
    console.error(e)
    process.exit(1)
  }
}

main()

CIでスクリプトを実行する

ciで呼びやすいようにscriptsに使うものは登録しときます

package.json
{
  "scripts": {
    "test-total-coverage": "jest --collectCoverage=true --coverageReporters=json-summary",
    "check-coverage": "ts-node --project scripts/tsconfig.json scripts/check-coverage/main.ts",
  }
}

※ts-nodeを実行する時はscript用のtsconfigを指定してます

あとは定義したスクリプトを呼んであげる(下記はcircleciの場合)
これで簡単なカバレッジのしきい値チェックがCI上できるようになりやす

config.yml
      - run:
          name: Report total coverage
          command: yarn test-total-coverage
      - run:
          name: Check total coverage
          command: yarn check-coverage

宣伝

Jest逆引き テストケースってタイトルでスクラップを作っており、他の方の投稿も許可してるので、コメントでも新しいテストケース(Jest単体のでも、Testing Libraryを使ったのでも、なんでも)でも書いてもらえるとうれしいデス!

https://zenn.dev/nus3/scraps/f1ea3cb4982593

脚注
  1. ここで言う簡単な とは、StatementsやBranches、Functionsのtotalのパーセントが一定の値を下回ってないかCIで軽くチェックしたいぐらいの温度感を指しています ↩︎

GitHubで編集を提案

Discussion