この記事は、ソフトウェアテストの小ネタ Advent Calendar 2017 の15日目の記事です。

ソフトウェアテストの小ネタ Advent Calendar 2017
https://qiita.com/advent-calendar/2017/software-testing-koneta

『なんとかlint』をCIツールで実行して
ソフトウェアの静的テストを実施している人も多いと思いますが。
このエントリでは、
Ruby on Railsで作られたアプリケーションに含まれる自然言語に対するテストを実施してみます。

textlintとは

textlintとは、
ルールに従って文書が記載されているかを自動でチェックする校正ツールです。

textlint
https://github.com/textlint/textlint

書籍やブログの執筆を行う際に、自動校正ツールとして使われています。

説明するよりも動きを見た方がわかりやすいので、
ここまで書いたこの文章に対してtextlintを実施してみます。
# ちなみに、このブログの記事はmarkdownで管理しています

以下のように「.textlintrc」を作ります。

{
  "plugins": [
    "markdown"
  ],
  "rules": {
    "preset-ja-technical-writing": {
      "max-ten": {
          "max": 6
      },
      "sentence-length": {
          "max": 160
      },
    },
    "spellcheck-tech-word": true,
    "no-mix-dearu-desumasu": {
      "preferInHeader": "",
      "preferInBody": "ですます",
      "preferInList": "である",
      "strict": true
    }
  }
}

node_modulesに、textlintを追加して実行します。

> yarn add textlint \
    textlint-rule-preset-ja-technical-writing \
    textlint-rule-spellcheck-tech-word \
    textlint-rule-no-mix-dearu-desumasu
> node_modules/.bin/textlint source/_drafts/

・・・/takemikami.com/source/_drafts/2017-12-14-draft.md
  15:25  error  弱い表現: "思います" が使われています。  preset-ja-technical-writing/ja-no-weak-phrase
  32:33  error  文末が"。"で終わっていません。           preset-ja-technical-writing/ja-no-mixed-period

✖ 2 problems (2 errors, 0 warnings)

このようにルールから外れているとエラーとして表示されます。

このチェックをRailsの言語リソースに対して適用することが、
このエントリで目指すところです。

Railsアプリ内の自然言語

Railsアプリケーションで自然言語が含まれるファイルは、
(行儀よく開発されていれば)
apps/views/config/locales/public/以下にあります。

Railsアプリケーションのディレクトリ構造のイメージ

+ apps
   + views
      + home
         + index.html.erb
+ config
   + locales
      + ja.yml
      + en.yml
+ public
   + index.html

つまり、以下のようにtexlintを実行すればチェック出来ることになります。
# config/locales以下はyaml形式以外のケースもありますが

node_modules/.bin/textlint app/views config/locales public

が、
textlintで、erbやyamlを対象として実行するpluginが無さそうなので。
プラグインを作ることにします。

textlintのプラグイン実装

ということで、yamlとerb用のpluginを作りました。

yaml用
https://github.com/takemikami/textlint-plugin-yaml

erb用
https://github.com/takemikami/textlint-plugin-erb
# erb用は中でhtmlのpluginを呼んでいるだけですが。。

以下のように追加します。

yarn add takemikami/textlint-plugin-yaml#master
yarn add takemikami/textlint-plugin-erb#master

「.textlintrc」は以下のように記載します。

{
  "plugins": [
    "yaml", "erb", "html"
  ],
  "rules":
※以降省略

次のコマンドで自動チェックを実行します。

node_modules/.bin/textlint app/views config/locales public

Railsアプリへのtextlint適用

これでtextlintを実行出来るようになったので、
次は、適用するルールについて考えてみます。

以下にtextlintで使えるルールの一覧があるので、ここからピックアップしていきます。

textlintのルール一覧
https://github.com/textlint/textlint/wiki/Collection-of-textlint-rule

ここでは、以下のルールを入れてみることにします。

  • textlint-rule-common-misspellings
  • textlint-rule-spellchecker

以下のように追加します。

yarn add textlint-rule-common-misspellings textlint-rule-spellchecker

以下のように「.textlintrc」を編集します。

{
  "plugins": [
    "yaml", "erb", "html"
  ],
  "rules": {
    "common-misspellings": { "ignore": [] },
    "spellchecker": {},
    "preset-ja-technical-writing": {
      "max-ten": {
          "max": 6
      },
      "sentence-length": {
          "max": 160
      },
    },
    "spellcheck-tech-word": true,
    "no-mix-dearu-desumasu": {
      "preferInHeader": "",
      "preferInBody": "ですます",
      "preferInList": "である",
      "strict": true
    }
  }
}

次のコマンドで自動チェックを実行できます。

node_modules/.bin/textlint app/views config/locales public

チェックが過剰な場合は、各ruleのパラメータを設定、
または、whitelistのfilterを使います。

textlint-filter-rule-whitelist
https://github.com/textlint/textlint-filter-rule-whitelist

以下のように「.textlintrc」にfilterを追加します。

{
※途中省略
  "rules": {
※途中省略
  },
  "filters": {
    "whitelist": { "allow": [ "word1", "word2" ] }
  }
}

# word1, word2の部分に対象外とする単語を入れておきます。

このように過剰なエラーを抑制しておくとCIにも組み込むことも出来ます。

これ以外にもprhで表記ゆれをチェックするのも有効だと思います。

textlint-rule-prh
https://github.com/textlint-rule/textlint-rule-prh

今後のこと

今回、yamlの値をtextlintに読ませるpluginを作成して、
Railsの言語リソースに対して、textlintのルールを適用出来るようにしました。

が、Railsの言語リソースのyamlには、
htmlやテンプレート変数が置かれたりもするので、
その辺りはきちんとpluginで対応する必要があります(私のTODOです)。
# 今は、ひとまずwhilelistに「%{」を登録して、無視させてますが。

ソフトウェアの品質を作り込む上で、
説明やメッセージのわかりやすさも大切な部分なので。
このように自動化して、効率的に品質を上げられると嬉しいなと思いました。

ソフトウェアのメッセージのBestPracticeをまとめた、
ルールのpresetとか作ると便利な気がする。