octocovはコードカバレッジを確認するCLIツールとしても使える

octocovは私が開発しているコードメトリクス計測のためのツールキットです。

主となる用途であるCI(GitHub Actions)に組み込む使い方は会社のテックブログで紹介させてもらいましたのでそちらをご覧ください。

tech.pepabo.com

私自身もドックフーディングをしていて、自分の主だったリポジトリはすでに octocov に移行済みです。

Fix handling for bind runner by k1LoW · Pull Request #47 · k1LoW/runn · GitHub

実は octocov にはもうひとつ便利な使い方があるので、そちらを紹介したいと思います。

コードカバレッジを確認する

octocov は実は単体のCLIツールとしても使うことができます。.octocov.yml といった設定ファイルも一切必要ありません。ただ、インストールするだけでOKです。

macOSだとHomebrew経由でインストール可能です。

$ brew install k1LoW/tap/octocov

あとは octocov が対応しているフォーマットカバレッジレポートを出力しているリポジトリでレポートファイルを指定して octocov コマンドを実行するだけです。

例えば、Goのプロジェクトだと以下のような感じです。

$ go test ./... -coverprofile=coverage.out -covermode=count
?       github.com/k1LoW/octocov        [no test files]
ok      github.com/k1LoW/octocov/central        3.682s  coverage: 73.1% of statements
?       github.com/k1LoW/octocov/cmd    [no test files]
ok      github.com/k1LoW/octocov/config 1.264s  coverage: 64.6% of statements
ok      github.com/k1LoW/octocov/datastore      1.690s  coverage: 43.0% of statements
?       github.com/k1LoW/octocov/datastore/artifact     [no test files]
?       github.com/k1LoW/octocov/datastore/bq   [no test files]
?       github.com/k1LoW/octocov/datastore/gcs  [no test files]
?       github.com/k1LoW/octocov/datastore/github       [no test files]
ok      github.com/k1LoW/octocov/datastore/local        0.796s  coverage: 80.0% of statements
?       github.com/k1LoW/octocov/datastore/s3   [no test files]
ok      github.com/k1LoW/octocov/gh     1.848s  coverage: 16.1% of statements
ok      github.com/k1LoW/octocov/internal       0.712s  coverage: 84.8% of statements
ok      github.com/k1LoW/octocov/pkg/badge      1.929s  coverage: 72.1% of statements
ok      github.com/k1LoW/octocov/pkg/coverage   2.606s  coverage: 88.4% of statements
ok      github.com/k1LoW/octocov/pkg/pplang     0.747s  coverage: 77.3% of statements
ok      github.com/k1LoW/octocov/pkg/ratio      1.062s  coverage: 83.2% of statements
ok      github.com/k1LoW/octocov/report 1.193s  coverage: 68.7% of statements
?       github.com/k1LoW/octocov/version        [no test files]
$ octocov -r coverage.out

                      main (9244fb7)
--------------------------------------
  Coverage                     66.8%

うまく Coverage が取得できていることが確認できたら octocov ls-files でファイルごとのカバレッジを見てみましょう。

$ octocov -r coverage.out ls-files
 73.1% [ 98/134] central/central.go
  0.0% [   0/29] config/build.go
 56.7% [ 89/157] config/config.go
 90.9% [  10/11] config/generate.go
 84.3% [ 91/108] config/ready.go
 77.8% [  42/54] config/yaml.go
 45.4% [ 49/108] datastore/datastore.go
  0.0% [    0/6] datastore/hint.go
 80.0% [  16/20] datastore/local/local.go
 16.1% [ 54/335] gh/gh.go
 83.9% [  52/62] internal/path.go
100.0% [    4/4] internal/value.go
 72.1% [  31/43] pkg/badge/badge.go
 91.5% [  43/47] pkg/coverage/clover.go
 91.7% [  44/48] pkg/coverage/cobertura.go
 84.7% [144/170] pkg/coverage/coverage.go
 96.7% [  29/30] pkg/coverage/diff.go
 90.9% [  40/44] pkg/coverage/gocover.go
 90.6% [  48/53] pkg/coverage/jacoco.go
 84.1% [  58/69] pkg/coverage/lcov.go
 90.6% [  29/32] pkg/coverage/merge.go
 89.9% [  62/69] pkg/coverage/printer.go
 87.8% [  65/74] pkg/coverage/simplecov.go
 77.3% [  34/44] pkg/pplang/pplang.go
 60.4% [  32/53] pkg/ratio/copy_from_gocloc.go
 92.9% [  26/28] pkg/ratio/merge.go
 94.2% [  81/86] pkg/ratio/ratio.go
 66.7% [132/198] report/diff_report.go
 70.2% [193/275] report/report.go

さらに octocov view でファイルを指定してテストがカバーしている行も確認できます。

$ octocov -r coverage.out view pkg/coverage/simplecov.go
[...]
112   3371              lcs := fcov.Blocks.ToLineCoverages()
113   3371              fcov.Total = lcs.Total()
114   3371              fcov.Covered = lcs.Covered()
115   3371              cov.Total += fcov.Total
116   3371              cov.Covered += fcov.Covered
117             }
118
119     11      return cov, rp, nil
120        }
121
122     16 func (s *Simplecov) detectReportPath(path string) (string, error) {
123     16      p, err := os.Stat(path)
124     16      if err != nil {
125                     return "", err
126             }
127     18      if p.IsDir() {
128      2              // path/to/coverage/.resultset.json
129      2              np := filepath.Join(path, SimplecovDefaultPath[0], SimplecovDefaultPath[1])
130      4              if _, err := os.Stat(np); err != nil {
131      2                      // path/to/.resultset.json
132      2                      np = filepath.Join(path, SimplecovDefaultPath[1])
133      2                      if _, err := os.Stat(np); err != nil {
134                                     return "", err
135                             }
136                     }
137      2              path = np
[...]

1列目が行数、2列目がテストにおいて通った回数、3列目が実際のコード行になります。

ターミナル上でカバレッジを確認できるのは意外に便利

私は今までファイル単位のコードカバレッジを見るためには、カバレッジレポートをHTMLで出力してブラウザで見たり、SaaSが提供している画面で見たりする方法しか持っていませんでした。

ターミナルでコードカバレッジをみるというのはターミナル内で開発をする自分のスタイルにもあっています。cat でファイルの中身をみるレベルでカバレッジもみることができるようになって便利です。

octocovは、Goのカバレッジフォーマットだけではなく、Rubyでよく使われるSimpleCovや、PHPUnitが出力可能なClover XMLや、Java/Kotlinでよく使われているらしいJaCoCoや、その他にもLCOVやCoverturaにも対応していますので、是非使ってみてください。