sbtにおけるテストの並列実行の設定詳細解説

いきなり本題というか、一番言いたいことを書くと、まず

テストの fork の設定によってぜんぜん違う。

という点があまり知られていない気がします。 *1

というか、自分も今回調べるまで、微妙に古い知識のままで完璧に知らなかったので、今一度理解した現時点での詳細を今書いています。

sbtにおいて、テストがどう並列化されるか?に関して、関係するというか、今回話すのは、以下の点です

  • Test / parallelExecutionというkey
  • Test / fork が true か falseか
  • concurrentRestrictionsというkey
  • testForkedParallelというkey

また、今から話すのはsbt 1.3.8時点の情報です。

さらに前提として、マシンのCPUのコア数によって挙動が異なる可能性がありますが、ひとまずそれなりに十分にコア数がある、として話を進めます。(少なくとも4以上) *2

*1:もちろん公式ドキュメントには書いてあるのでそれは読みましょうというか、完璧に読んだことある人は、このblog読む必要ないはずです https://www.scala-sbt.org/1.x/docs/Testing.html

*2:specs2などは、更に別の概念として、1つのテストclass内のテスト並列実行する機能があったはずですが、今回はsbt自体の機能の話なので、そこには触れません

続きを読む

CircleCI上でsbtのインクリメンタルコンパイラのキャッシュが効かなくて再コンパイルされる問題

結論としては以下のissueに大体全部書いてあります。

Incremental compilation inside docker container broken since SBT 1.1.0 · Issue #4168 · sbt/sbt · GitHub

依存ライブラリのjarのキャッシュではなく、あくまでインクリメンタルコンパイラのキャッシュの話です。

簡単に現象をまとめると

続きを読む

wartremoverを使ってscalapbのapplyのデフォルト引数を禁止する

というのを作りました。

scalapbというのは、scala向けのprotocol buffersやgRPCのためのライブラリですが、protobufのmessageに対応するcase classのコンパニオンオブジェクトのapplyには、すべて(protobuf上のデフォルト値と同様の)デフォルト引数が設定されています。

これは便利なときもあるのですが、意図せず使ってしまってバグることも多いので、以前自分がpull reqして、デフォルト引数がないファクトリーメソッドを別途追加したことがありました。

github.com

つまりデフォルト引数によるミスを防ぎたい場合は、こっちの "of" を使えばいいです。 そして、ofに書き換える箇所を探すのにあたって、大量にあって探しづらいのでwartremoverでwarnかerrorにしてくれるものを作りました。

(wartremoverには、デフォルト引数の"定義"を警告するやつはあるけど、使用側はない?どちらにしろ、他のやつは許容して、scalapbのやつだけ警告したかったので作った)

本当はscalafixで自動書き換え作りたかったのですが、そんなにすぐに作れる能力がなかったので、誰か作って・・・。

gist.github.com

scalapropsをdotty対応してみた知見

まだ継続してメンテナンスするかどうかわからないけど、以下のようなニュースが飛び込んで来たので、そろそろ試すか、と試した結果をメモ。

結果としては数十分から数時間書き換えた程度で、それなりに動きました。

最初scalazをやろうかとおもったけど、kind-projectorがコンパイラプラグインだから、そのままでは不可能そうなのでscalapropsにしました。

続きを読む

sbtで依存しているprojectのみにcleanなどの特定のタスクを実行する

以下のような質問を某所で受けたので

f:id:xuwei:20191218131602p:plain

書きました

gist.github.com

既にあるとか、もっといい感じに書ける、みたいなのがあればお知らせください。

ちなみに、デフォルトでは単体のprojectしかcleanしないのは、完全にsbt的には意図した挙動のはずです。 デフォルトが今回自分が書いたような挙動では、逆に特定の単体のprojectだけをcleanしようとすると手段がなくて困るので。とはいえ、その手段が提供されていればデフォルトのcleanの挙動がそっちでも困らない?といえるかもしれませんが。

sbtですべてのsub projectの特定のtaskを直列に実行するtaskを自動でつくる

要点をまとめると

  • TaskではなくCommandでやってしまうなら少し簡単だが、(stateなどの他のkeyに依存して)taskからtaskを生成するには多少コツがいる(Def.taskDynを使う)
  • なおかつ、sub projectの列挙を全自動でやりつつtaskを生成するのが多少コツがいる( Project.extractして、.structure.allProjectRefsする部分)

みたいな感じなんですが、とりあえずもう答を貼っておきます。すでに誰か作っていそうな気もするので、そしたら教えて下さい

gist.github.com

"sub projectの列挙を全自動で" は(自分にとっては)とても重要で、なぜかというと、仕事でこれ必要になったんですが、仕事のprojectはmonorepoでsbtのprojectが、このblog書いてる時点で81個あるので(今後も増える可能性あり)、明示的に列挙なんて絶対にやりたくない、という理由です。

mockitoとscalatestについて

以下の投稿について、編集リクエストするレベルではないし、コメントするにも論点が多すぎてすごく長くなるため、別記事として自分のblogに書くことにしました

qiita.com

続きを読む