Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

Millのテストディレクトリはsbtと構成が違うので注意

ScalaのビルドツールであるMillでテストを書こうとしたらsbtとディレクトリ構成が違っていて詰まっていたのでその違いを記しておく。

% mill --version
Mill Build Tool version 0.11.2
Java version: 18.0.2, vendor: Amazon.com Inc., runtime: /home/windymelt/.asdf/installs/java/corretto-18.0.2.9.1
Default locale: ja_JP, platform encoding: UTF-8
OS name: "Linux", version: 6.3.9-1-default, arch: amd64

おさらい: sbtでテストを書くときのディレクトリ構成

sbtではテストはsrc/test/にソースコードを配置する。

└── (project root)
    └── src
        ├── main
        └── test

testのソースコードではtestコンフィギュレーションを指定したライブラリがクラスパスに導入され、テストフレームワークが利用できるようになる。

コンフィギュレーションについては拙著の記事を参照。

blog.3qe.us

Millでテストを書くときのディレクトリ構成

Millにはテストコンフィギュレーションというものが存在しない。このことはドキュメントにも何度も書いてある。

mill-build.com

ではどうやって「テストのときだけ依存するライブラリ」を表現するかというと、本体モジュールの下にテストモジュールをネストさせることで、本体モジュールの依存性をテストモジュールに引き継がせる。

ビルド定義は以下のようになる:

import mill._, scalalib._

// トップレベルのモジュール。本体の実装がある
object app extends RootModule with ScalaModule {
  def scalaVersion = "3.3.0"
  def publishVersion = "0.1.0-SNAPSHOT"

  // appの下にtestモジュールを配置する。ここでmunitに依存する
  object test extends ScalaTests with TestModule.Munit {
    def ivyDeps = Agg(ivy"org.scalameta::munit::0.7.29")
  }
}

2つの原則さえ覚えておけば役に立つ。1. Millではモジュールはそのままディレクトリになる。2. ソースコードはモジュールディレクトリのsrcディレクトリに置く。これに加えて、RootModuleを継承しているモジュールはモジュールディレクトリを省略してそのままsrcディレクトリを置ける。今回の場合は、appRootModuleを継承しているのでそのままsrc/ディレクトリを置き、その下にあるtestモジュールのためにtestディレクトリを置く。

└── (project root)
    ├── src
    │   └── Foo.scala
    └── test
        └── src
            └── FooSuite.scala

ディレクトリ構成は上掲のようになる。

sbtからの差分

sbtからMillに入ってきた人は、以下の点に注意する必要がある:

  • srcの下にmaintestディレクトリは存在しない
    • Millでは直接パッケージ階層が始まる。
  • テストコードは、テスト対象のモジュールにネストしたモジュールとして構成する
    • ネストすると依存性を引き継げる

ビルドしたい単位がそのままディレクトリになるという設計思想さえ覚えておけば、あまり難しくはない。sbtでは1つにまとめられているが、Millではそのように扱わない。

これを知らなかったため、[E006] Not Found Errorがたくさん出て困ってしまった。テストライブラリを入れてるのにな〜と思っていたところ、そもそもディレクトリ構成の作法も別だったというだけの話だった。ビルドツールが違えばディレクトリ構成も変わる。よく考えれば当たり前だ。

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?