これ https://github.com/sbt/test-interface
scalaprops https://github.com/xuwei-k/scalaprops/ を作成するにあたって実際使ったが、最低限は理解したが最低限しか理解してなくて、色々わからないことだらけなので、わかっていることをメモするのと、疑問点などを雑に列挙していく
まず基本的な概要的な、自分が理解してること
- sbtからテストライブラリを呼び出せるようにするために「テストライブラリ作成者側が」使うもの
- 頻繁に更新すると互換性が大変なことになるので、2年とかそういう単位でわざと頻繁に更新はしていないようだ
- Scalaのバイナリ互換問題回避のためpure javaで作られている
- 古いclassも互換性のために残されていて、同じjarに3世代くらい残ってて、どれが最新のものなのか一瞬わかりづらいので注意
- 最初、実際間違って古いほうをつかってしまって、あとで書き換えが発生してつらかった
- ここの"New"というコメントに騙された(´・ω・`) https://github.com/sbt/test-interface/blob/v1.0/src/main/java/org/scalatools/testing/Runner2.java#L3
- パッケージがsbt.testingではじまるのが新しいやつ https://github.com/sbt/test-interface/tree/v1.0/src/main/java/sbt/testing
- パッケージがorg.scalatoolsではじまるのは古いやつ https://github.com/sbt/test-interface/tree/v1.0/src/main/java/org/scalatools/testing
- 最初、実際間違って古いほうをつかってしまって、あとで書き換えが発生してつらかった
- 以下、代表的なテストライブラリの実際の使用例のコード
- https://github.com/etorreborre/specs2/blob/SPECS2-3.6/core/src/main/scala/org/specs2/runner/SbtRunner.scala#L6
- https://github.com/scalatest/scalatest/blob/release-3.0.0-M15-for-scala-2.11-and-2.10/scalatest/src/main/scala/org/scalatest/tools/Framework.scala#L18
- https://github.com/scalameter/scalameter/blob/e8193e8a/src/main/scala/org/scalameter/ScalaMeterFramework.scala#L5 scalameterは古いほう使っているようだ
- 「古いほうの消す予定」や「いや別に新しい方の機能必要ないなら、今でも古い方使っていいよ?」というあたりが理解できてない
- scalacheckは
- scalapropsも一瞬scalacheckを真似してscala-js対応やろうかとおもったけど、test-interfaceの理解が追いつかないし、色々あれなのでとりあえずやめた
- 将来的にscala-js対応をやる可能性はゼロでもないが、とりあえず、すぐにやる予定ない
ここから下は、疑問点、課題などを中心に
- RunnerのtasksメソッドがTaskDefの配列受け取ってTaskの配列返す、というインターフェイスの意味を完全に理解できてない
- https://github.com/sbt/test-interface/blob/v1.0/src/main/java/sbt/testing/Runner.java#L42
- 今のところ、それぞれの1つのTaskDefから1つのTask、つまり同じ数だけ生成して返してるけど、それ以外のパターンありえるのだろうか?(1つ受け取って、2つ返す、など)
- テストがforkされた場合に正しく動くのか怪しい
- forkされた場合には、なにを気をつけないといけないのか、がそもそもわかってない(なにか違う処理をする必要ある?)
- TaskのexecuteでまたTaskの配列が返せる意味がわかってない
- https://github.com/sbt/test-interface/blob/v1.0/src/main/java/sbt/testing/Task.java#L36
- 今は固定でゼロの配列返してる
- https://github.com/xuwei-k/scalaprops/blob/705c83db9/scalaprops/src/main/scala/scalaprops/ScalapropsRunner.scala#L189
- そもそもTaskとは・・・。「Task = 1つのテスト」を表現してるのか、それとも違う概念なのか?
- 仮に「Task = テスト」だと、「一つのテストを実行することにより、新たに別のテストが生まれる可能性がある」ということになるが、なんだそれ???
- Taskにtagsというメソッドあるけど、全く使ってない(ある程度の用途は想像つくけど、完全に理解してないので後回し)
- テスト終わったときのメッセージ
- https://github.com/xuwei-k/scalaprops/blob/705c83db92f90eaf8a4de1c561a90db1b70a8749/scalaprops/src/main/scala/scalaprops/ScalapropsRunner.scala#L201
- これって自分でテスト数をカウントしておかないと、最後に総テスト数の表示とかしてくれないんですか?
- Loggerの使い方
- 進捗表示するために、一文字ずつ同じ行にドットをprintしていこうとしたら、test-interfaceが提供するLoggerは必ず改行される仕様らしい?
- たぶん並列に対応するため?
- なので、printやprintlnを直接呼び出すという酷いことをしている(改善したい)
- スレッドの使い方
- sbt側で、並列なのか?使っていいスレッド数いくつなのか?の指定があるはず?
- どこから取得するのかわかってない(めんどうなので調べてない)
- マナーというか慣習的に、スレッド生成していいのか?生成する場合はどうやってやるべきなのか理解してない
- いまは、scalaz.concurrent.Taskの実行のために、内部でスレッドプール作ったりしてる(ただし、timeoutのために使ってるだけで実質並列実行はしていない)
- そのあたりいい感じにしたい
- Serializable
- sbtから使われるクラスをSerializableにしておかないと、(forkした場合に?)残念になる気がしたけど、そのあたりしっかりできているのか未検証
- Listener
- なぜか独自のListenerを作ったが https://github.com/xuwei-k/scalaprops/blob/705c83db92f90eaf8a4de1c561a90db1b70a8749/scalaprops/src/main/scala/scalaprops/ScalapropsListener.scala sbt側にも同じような仕組みある程度ある気がするので、整理する必要があれば整理。
- (test-interfaceの話に直接関係ないが)そもそもListenerのインターフェイスが雑なので、今後この部分変える可能性高い
- Fingerprint
- テストとなるクラスやメソッドを指定するやつ?(別の言い方をすると)sbtがテストとなるclassなどを見つけるための目印となるもの
- SubclassFingerprintしか理解してない、他の使い方を理解してないので、とりあえずこれだけ使っているが、他のものもちゃんと理解して、必要なら使ったほうが良さそう
- https://github.com/xuwei-k/scalaprops/blob/705c83db9/scalaprops/src/main/scala/scalaprops/ScalapropsFingerprint.scala
- Event
- event受け取るメソッドがあるし、とりあえずコレ作って渡せばいいんだろ?という程度の認識
- sbt側でこれを受け取った後、どのように使われるのかよくわかってない
- https://github.com/xuwei-k/scalaprops/blob/705c83db92f90eaf8a4de1c561a90db1b70a8749/scalaprops/src/main/scala/scalaprops/ScalapropsEvent.scala
- これがたぶんSerializableである必要がある?
- 最近のversionから入った、sbtがjunit用の結果のxmlを生成するのに使う、とかだろうか?
- durationとかあるけど、それをいい感じにsbt側で表示する機能とかあるのだろうか・・・
- skippedとか、いくつかのイベント、一部には処理書いてあるけど、結局それを生成する仕組み用意してない?ので、渡されないかもしれない
疑問点は、たぶんspecs2やscalatestのコードを読むのが(面倒だが)一番確実な方法のはずなので、まぁ気が向いたら頑張って読みます・・・