🧑‍🎓

Clojure のテストランナー kaocha 入門

2021/12/29に公開

この記事は Clojure Advent Calendar 2021 20日目の穴埋めに向けたものです。

はじめに

Clojure のテストランナーには何を使っているでしょうか?
Leiningen であれば lein test があるのでまず悩む必要はないでしょうが、Clojure CLI の場合、標準でテストランナーは提供されていないので自分で選ぶ必要があります。

第一候補としては Cognitect 謹製の test-runner でしょうか?
https://github.com/cognitect-labs/test-runner

ポスト lein test としては十分だと思います。しかしここでは kaocha をもう1つの候補として紹介したいと思います。

kaocha

https://github.com/lambdaisland/kaocha

kaocha は lambdaisland 謹製のテストランナーで、元々多機能なことに加えてプラグインでその機能をより拡張できるのが大きな特徴です。

lein test だけ使っていると分かりづらいかも知れませんが、テストランナーが多機能とはどういうことでしょうか?
わかりやすいところで言うと以下のようなことです。

  • テスト順のランダム化
    • 実行の順番に依存してしまっているテストが失敗し、発見できるようになります
  • 失敗時のテスト停止
    • 全体のテストを実行するのに時間がかかるケースだと、失敗即停止した方が時間を節約できます
  • プロファイリング
    • どのテストケースが遅いのかがわかります

簡単な使い方

多機能とは言え使い方は簡単です。
以下のような deps.edn を用意して clojure -M:test を実行するだけです。

{:deps {org.clojure/clojure {:mvn/version "1.10.3"}}
 :aliases
 {:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.60.972"}}
         :main-opts ["-m" "kaocha.runner"]}}}

GitHub 上の README には bin/kaocha を用意する手順が書かれていますが、Clojure CLI から直接実行する方が手間がないので私はこの方法でテストをしています。

デフォルトでは src ディレクトリがソースファイル、test ディレクトリがテストファイル、-test で終わる namespace がテスト対象として扱われます。

設定ファイル

上記の簡単な使い方でテストを実行すると以下のような警告メッセージがでるかと思います。

WARNING: Did not load a configuration file and using the defaults.

kaocha では実行時にオプションとしてどのようにテストを実行するかの指定が可能ですが、tests.edn という設定ファイルを用意して実行するのが基本になります。

https://cljdoc.org/d/lambdaisland/kaocha/1.60.972/doc/3-configuration

例えば以下のような内容です。

#kaocha/v1
{;; テスト結果を色付けする
 :color? true
 ;; テスト結果を TAP 形式で出力する
 :reporter [kaocha.report/tap]
 ;; テスト順をランダム化
 randomize? true
 ;; 失敗したらテストをその場で終了する
 :fail-fast? true}

なお tests.edn は juxt/aero を使って読み込まれるので、aero で提供されている #env による環境変数の参照や #include による外部 EDN ファイルの読み込なども可能です。

設定ファイルはプロジェクトルートに tests.edn という名前で存在してさえいればいいので、ファイルを用意したら最初と同じように clojure -M:test を実行すれば勝手に読み込まれてテストが実行されます。

プラグイン

前述の通り、kaocha はプラグインによってその機能をより拡張することが可能です。

https://cljdoc.org/d/lambdaisland/kaocha/1.60.972/doc/8-plugins

kaocha 本体に組み込まれているプラグインもあり、それらは上記の設定ファイルで有効化できます。

https://github.com/lambdaisland/kaocha/tree/main/src/kaocha/plugin

例えば以下のように設定すると profiling, print-invocations プラグインが有効になります。

#kaocha/v1
{:plugins [;; テスト終了時に遅いテストケースを表示
           :kaocha.plugin/profiling
           ;; 失敗したテストを再実行できるコマンドをテスト終了時に出力する
           ;; コピペしてすぐに試せるように
           :kaocha.plugin/print-invocations]}

これ以外にもテストの終了を通知するプラグインやテスト実行の前後などに特定の処理を追加するフックプラグインなどもあるので興味のある方はドキュメントを読んでみてください。

外部プラグイン

ここまでは kaocha に組み込まれている内部のプラグインを紹介しましたが、kaocha プラグインは当然外部ライブラリとしても公開可能です。
以下はいずれも lambdaisland 製のものですが、kaocha とは別リポジトリとして公開されている kaocha プラグインです。

ClojureScript

https://github.com/lambdaisland/kaocha-cljs

ClojureScript のテストをサポートするプラグインです。
別途 Node.js の ws ライブラリをインストールする必要がありますが、それさえ用意できれば以下のような tests.edn を用意して clojure -M:test --focus :unit-cljs で ClojureScript でのテストが実行できます。

  • deps.edn
    {:deps {org.clojure/clojure {:mvn/version "1.10.3"}}
     :aliases
     {:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.60.972"}
                          ;; 依存ライブラリとして追加
                          lambdaisland/kaocha-cljs {:mvn/version "1.0.107"}}
             :main-opts ["-m" "kaocha.runner"]}}}
    
  • tests.edn
    #kaocha/v1
    {:tests [{:id :unit-cljs
              :type :kaocha.type/cljs}]}
    

なお設定が簡単な分いくつか制限があり、それを解決するための lambdaisland/kaocha-cljs2 というプラグインもあります。

https://github.com/lambdaisland/kaocha-cljs2

こちらは個人的に使ったことがないので解説はできないのですが、README を読む限りだと初期設定が面倒なようなのでシンプルなプロジェクトにおいては kaocha-cljs (v1) がおすすめのようです。

To get around these limitations we created kaocha-cljs2, which is infinitely flexible, but significantly harder to set up. For simple projects and libraries kaocha-cljs v1 can still be a valid choice. If it no longer serves your needs, you can try your hand at kaocha-cljs2.

カバレッジ

https://github.com/lambdaisland/kaocha-cloverage

Clojure でのカバレッジ計測でお馴染みの Cloverage と連携するプラグインです。
以下のように cloverage プラグインを有効化しておくだけで、clojure -M:test の実行時にカバレッジを計測/表示してくれます。
Cloverage 単体で使う場合だとカバレッジ計測時にテストが走るので、通常のテスト実行の代わりに Cloverage を実行するといったやり方になりがち(?)で、テスト実行がどこで行われているのかがわかりづらくなってしまいますが、このプラグインを使うとテストついでのカバレッジ計測になるので挙動としてもわかりやすいかと思います。

  • deps.edn
    {:deps {org.clojure/clojure {:mvn/version "1.10.3"}}
     :aliases
     {:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.60.972"}
                          ;; 依存ライブラリとして追加
                          lambdaisland/kaocha-cloverage {:mvn/version "1.0.75"}}
             :main-opts ["-m" "kaocha.runner"]}}}
    
  • tests.edn
    #kaocha/v1
    {:plugins [;; カバレッジの計測
               :kaocha.plugin/cloverage]
    
     ;; :kaocha.plugin/cloverage プラグインの設定
     :cloverage/opts {:src-ns-path ["src"]
                      :test-ns-path ["test"]
                      :ns-exclude-regex ["foo.bar.*"]}}
    

最後に

子供が起きるまでの時間に書こうと駆け足の紹介になってしまい申し訳ないです。
誤字脱字などありましたらご指摘いただければと思います。

kaocha はとても便利なのに日本語での記事がほとんどなく勿体ないなと思っていたので、この記事を参考に手を出してみていただければと思っています。

Discussion