dog用のautodocライブラリを作った

Rubyにはautodocというライブラリがあります。

r7kamura/autodoc · GitHub

これのdog用のライブラリを作りました。

pocketberserker/dog-autodoc · GitHub

dog-autodoc用のsbtプラグイン実装中です…最低限部分できたので一旦リリースしました。

pocketberserker/sbt-dog-autodoc · GitHub

モチベーション

Scalaにはplay-autodocというものが存在する。

krrrr38/play-autodoc · GitHub

でもこれ、Play Framework用なんですよね。ということで

  • Playに依存しないものにしたい
  • どうせだからクライアントは切り替えたい -> httpzを使おう

というのがモチベーションです。

苦労した点

  1. sbtから出力ディレクトリを設定しつつ
  2. テストを一回だけ実行し
  3. 実行後に出力する

この流れをどうやってみたすかかなり悩んだ。 というか、当初の想定より随分と変わっている(テストの実装ミスしてて当初想定していた残骸がゴミコミットとして残ってしまった…orz)。

最終的には、

  • Autodoc用のTestFrameworkを登録しておく
  • AutodocMarker型の値が結果となっているケースのみ特別な処理をしてからイベントを登録する
    • Autodocは実行したテスト結果とテストケース名から文字列をジェネレートできる
    • Event#fullyQualifiedNameにクラス名を入れるので、あとは出力結果(文字列)をどうにかしてEventに持たせれば保存に必要な情報が揃う
    • ところで、出力が可能なのはテストに成功したときのみ
    • テスト成功時には通常Event#throwable.isDefinedfalseを返すはずである。なぜなら、テスト成功なのに例外が投げられている状態は矛盾しているからだ。
    • 実際JUnit Reporterはこの組み合わせを無視している https://github.com/sbt/sbt/blob/v0.13.9/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala#L84
    • つまり、この使われないであろうEvent#throwableに出力を押し込んでおくことで、ファイル書き出しをsbt内だけで完結させることができる
  • https://github.com/sbt/sbt/blob/v0.13.9/testing/src/main/scala/sbt/TestReportListener.scala#L9 を使ってイベントを取得してテスト終了時に保存

という形に。ひどい実装だ…。

こういう形になった最大の要因は型パラメータが邪魔をしてリフレクションでの取得 or 型の変換が難しかったからですね。以下そのときのxuwei-kさんのアドバイス。

こういうときはType erasureが辛く感じます…。 結局、autodocのためにdog自体をいじるのはなんとなくいやだったので採用しませんでした。

まとめ

dogの作りが従来のユニットテスティングフレームワークと異なるからこういうときつらい…でもがんばる。

今後は安定かとかconsole用のWriterを復活させるかどうかあたりですかね。 あ、あとrename…ひどい命名ばかりしているので良い名前母種中です。