文章カバレッジ

以前、技術文書をソフトウェア開発する話textlintGitBookを使って文書を開発する方法についてお話しました。

その時に、自然言語のチェックの自動化などはまだ色々考えられることがあるという話をしました。

文書のテストはまだまだ色々できることがある
カバレッジを取るとかメトリクスを取るとか
まとめ1 | 技術文書をソフトウェア開発する話

そこで文章のカバレッジというものを考えて実装してみました。

textlintとコードカバレッジの仕組みを使ったものですが、こういうのをなんと呼べばいいのかよくわからなかったので、ここではとりあえず”文章カバレッジ”と読んでいます。

textlintは全ての文に対してLintを実行するので命令網羅と近い感じがします。

命令網羅(statement coverage:SC)
コード内のすべての命令が少なくとも1回は実行されるようにテストを設計する。欠陥検出力は弱い – 情報システム用語事典:カバレッジ基準(かばれっじきじゅん) - ITmedia エンタープライズ

よくよく考える仕組み的にカバレッジではないので、何か別の名前が必要な気がします。

カバレッジ

具体例がないとイメージしにくいと思うので、azu/JavaScript-Plugin-Architectureを例にしてみます。

JavaScript-Plugin-Architectureという文書では今回作ったtextlintの文章カバレッジを表示しています。

codecov.io

coverage graph

textlintから既存のコードカバレッジのフォーマットであるlcovを出力出来るようにしているので、Coverallsなどコードカバレッジサービスとそのまま連携することができます。

コマンドラインからもこのカバレッジを表示することができます。 lcovファイルを渡すとそのカバレッジを表示してくれるlcov-summaryというCLIを書いたのでそれを利用しています。

npm run textlint:coverage

> [email protected] textlint:coverage /Users/azu/.ghq/github.com/azu/JavaScript-Plugin-Architecture
> summary-to-path | xargs textlint -c coverage.textlintrc -f lcov | lcov-summary


Code Coverage Results:

 96.83% (61/63) README.md
 92.59% (25/27) ORGANIZATION.md
 97.60% (122/125) ja/jQuery/README.md
 96.45% (299/310) ja/ESLint/README.md
 95.59% (195/204) ja/connect/README.md
 96.38% (293/304) ja/gulp/README.md

Total Coverage:  96.32%

仕組み

仕組みは意外と簡単で、既存のパーツを組み合わせて動くようにしました。

textlintのLintの結果は”compact”, “checkstyle”, “jslint-xml”, “junit”, “tap”, “pretty-error”, “json”などの形式で出力できます。 それらに加えて、コードカバレッジのフォーマットであるlcovcodecovを作りました。

Codecov JSONフォーマットはCodecov用の形式ですが、他のコードカバレッジにはないメッセージ情報を含めることができます。

これを利用すれば、Codecov上にカバレッジとメッセージ(Lintのエラーメッセージ)を表示することができます。

architecuture

カバレッジの結果として

  • textlintで問題がなかった行を1
  • textlintで問題があった行を0

としています。(マイナスとか小数点をサポートしてない場合もあるので1と0という風にしてます)

文章カバレッジのモチベーション

この仕組みのモチベーションについて書いておきます。

ESLinttextlintなどのLint系に共通する話ですが、LintはCIに入れるとユニットテストに比べて、スタイルに近いチェックが多いためCIを落としやすいです。

厳しいスタイルのチェックをLintで行うと毎回のようにCIが落とすので、厳しめのルールは入れにくい気がしています。

Lintはエディタなどの書く環境に統合してリアルタイムでチェックするのが一般的だと思いますが、そうした場合でも厳しめのルールを一つ入れるだけで大量のエラーがでるため書くモチベーションを奪ってしまうことがあります。

この場合、FAIL/PASSという極端な結果ではなく、WARNINGやINFOというようなレベルを間に入れることで解決するように思えますが、そういった情報に慣れてしまうと無視してしまうのが人間です。

そのため、警告などの情報を上手く扱える必要があると思っていました。カバレッジは百分率で値がでるので、そういう中間的な状態を扱いやすいと思います。

これを利用すると普通に書いてて落としてしまうような厳しめのルールが導入しやすいと思いました。

例えば、azu/JavaScript-Plugin-Architectureでは通常全て通ってるべき.textlintrcと厳しめのルールを採用したcoverage.textlintrcを使っています。

カバレッジにはcoverage.textlintrcを使ったtextlintの結果をCodecovに送っています。

こうすることで、普通に書いてると入れるのが難しいルールも取り入れやすくなり、後でCodecov上で特定のファイルだけ妙に数値が落ちてることなどが発見できます。

チェック結果を継続的に数値化して見ることが出来ることを実現したくて、そういう仕組みを持っている既存のコードカバレッジの仕組みに乗ったという感じです。

なのでやっぱりカバレッジではない気はしています。

多分これはJenkinsで静的解析の警告数レポートを出すのと似たような話なのだと思います。

使い方

使い方は単純でtextlintのformatterとして実装してあるので

例えば、textlint-formatter-lcovならインストールして-f lcovと指定すればいいだけです。

npm install -D textlint textlint-formatter-lcov
$(npm bin)/textlint -f lcov README.md
# lcov形式で結果が出力される
$(npm bin)/textlint -f lcov README.md -o lcov.info
# ファイルとして保存する

Codecovへカバレッジを送りたい場合textlint-formatter-codecovを使って

npm install -D textlint textlint-formatter-codecov codecov.io
$(npm bin)/textlint -f codecov README.md | codecov

とするだけです。

CodecovはPull Request毎にカバレッジを書いてくれるBotとかもあるので面白いです。

codecov bot

おわり

textlintを使って文章カバレッジ?を取る方法について書きました。

最初はtextstatを使ってメトリクスを継続的に取る方法を探していましたが、途中でコードカバレッジの仕組みをLinterにも持ってくれば面白いのではないかと気づきました。

この仕組みはESLintとか他のLintでもlcov形式で出力すればできるので、Lintカバレッジレポートみたいなものなのかもしれません。

Travis CIとかと連携してコミットに紐付いて特定の値を貯めることが出来るウェブサービスがあったらまた別の方法がとれるかもしれません。

Google Analyticsとかで実現できそうですがあんまり使いやすくないです。

技術文書をソフトウェア開発する話でも話していましたが、文章に対するプログラミング言語のようなツールはまだまだ少ない印象です。 (研究から出てるツールはあるけど、特定のユースケースをはみ出ると使えなくなる印象)

文書もCIを回して開発するのがもっとあたりまえになってくると、もっと面白いことが色々起きるのではないかと思っています。