dog用のautodocライブラリを作った
Rubyにはautodocというライブラリがあります。
これのdog用のライブラリを作りました。
pocketberserker/dog-autodoc · GitHub
dog-autodoc用のsbtプラグインは実装中です…最低限部分できたので一旦リリースしました。
pocketberserker/sbt-dog-autodoc · GitHub
モチベーション
Scalaにはplay-autodocというものが存在する。
でもこれ、Play Framework用なんですよね。ということで
- Playに依存しないものにしたい
- どうせだからクライアントは切り替えたい -> httpzを使おう
というのがモチベーションです。
苦労した点
- sbtから出力ディレクトリを設定しつつ
- テストを一回だけ実行し
- 実行後に出力する
この流れをどうやってみたすかかなり悩んだ。 というか、当初の想定より随分と変わっている(テストの実装ミスしてて当初想定していた残骸がゴミコミットとして残ってしまった…orz)。
最終的には、
- Autodoc用のTestFrameworkを登録しておく
- AutodocMarker型の値が結果となっているケースのみ特別な処理をしてからイベントを登録する
- Autodocは実行したテスト結果とテストケース名から文字列をジェネレートできる
Event#fullyQualifiedName
にクラス名を入れるので、あとは出力結果(文字列)をどうにかしてEventに持たせれば保存に必要な情報が揃う- ところで、出力が可能なのはテストに成功したときのみ
- テスト成功時には通常
Event#throwable.isDefined
はfalse
を返すはずである。なぜなら、テスト成功なのに例外が投げられている状態は矛盾しているからだ。 - 実際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さんのアドバイス。
@pocketberserker Scalaのリフレクション、(少なくとも2.10だと)スレッドセーフじゃないけど、2.10サポート諦める(もしくは頑張ってロックとって頑張る)んですか?
(さらに、2.11でもまだ直ってないという噂もある)
— Kenji Yoshida (@xuwei_k) September 3, 2015
@pocketberserker TestCaseをtype aliasやめて
case class TestCase[A](value: Kleisli[TestResult, Endo[Param], A])(implicit A: ClassTag[A])
とか?
— Kenji Yoshida (@xuwei_k) September 3, 2015
こういうときはType erasureが辛く感じます…。 結局、autodocのためにdog自体をいじるのはなんとなくいやだったので採用しませんでした。
まとめ
dogの作りが従来のユニットテスティングフレームワークと異なるからこういうときつらい…でもがんばる。
今後は安定かとかconsole用のWriterを復活させるかどうかあたりですかね。 あ、あとrename…ひどい命名ばかりしているので良い名前母種中です。