Real projects need a build, dependencies and tests; sbt is the most widely used Scala build tool.
sbt is the standard Scala build tool. A minimal project is a build.sbt plus project/build.properties (pinning the sbt version) and sources under src/main/scala and tests under src/test/scala. Start the sbt shell once with sbt and run tasks inside it, keeping the JVM warm: compile, run, test, testOnly *ParserSuite, console and ~test (rerun on file changes).
Dependencies use the form "org" %% "artifact" % "version". The double %% appends the Scala binary version (_3) to the artifact name, picking the build for your Scala version; a single % is for plain Java libraries. Test-only libraries get % Test. Multi-module builds define several projects with lazy val core = project.in(file("core")) and dependsOn.
MUnit is a lightweight testing library that works with sbt and Scala CLI. A test suite extends munit.FunSuite and declares test("name") { ... } blocks with assertEquals(obtained, expected), assert(cond) and intercept[Ex] { ... }. It prints readable diffs on failure. ScalaTest is the older, larger alternative, and ScalaCheck adds property-based tests.
For single-file work, Scala CLI handles tests too: files ending in .test.scala with //> using test.dep org.scalameta::munit::1.1.0 run with scala test ..
Example
// build.sbt
ThisBuild / scalaVersion := "3.7.1"
lazy val root = project
.in(file("."))
.settings(
name := "calc",
libraryDependencies ++= Seq(
"com.lihaoyi" %% "upickle" % "4.1.0",
"org.scalameta" %% "munit" % "1.1.0" % Test
)
)
// src/test/scala/CalcSuite.scala
class CalcSuite extends munit.FunSuite:
def divide(a: Int, b: Int): Either[String, Int] =
if b == 0 then Left("division by zero") else Right(a / b)
test("divides evenly") {
assertEquals(divide(10, 2), Right(5))
}
test("rejects zero") {
assert(divide(1, 0).isLeft)
}
// $ sbt test -> + divides evenly, + rejects zero, Passed: Total 2Remember
- build.sbt declares settings; run tasks in the sbt shell
%%picks the artifact built for your Scala version;% Testscopes it- MUnit: extend FunSuite, write
test(...)with assertEquals ~testreruns tests on every save
Watch out for
- Using a single % for a Scala library, which fails to resolve or pulls in the wrong binary version.