Skip to main content


The test command runs test suites in the test sources. Test sources are complied separately (after the 'main' sources), and may use different dependencies, compiler options, and other configurations.

By default, all command line options apply to both the main and test sources, so using directives (or special imports) can be used to provide test-specific configurations.

Test sources

A source file is treated as test source if:

  • it contains the //> using target.scope "test" directive, or
  • the file name ends with .test.scala, or
  • the file comes from a directory that is provided as input, and the relative path from that file to its original directory contains a test directory

The last rule may sound a bit complicated, so let's explain it using following directory structure:

├── a.scala
├── a.test.scala
└── src
├── main
│ └── scala
│ └── d.scala
├── test
│ └── scala
│ └── b.scala
└── test_unit
└── scala
└── e.scala

Given that directory structure, let's analyze what file(s) will be treated as tests based on the provided inputs.

scala-cli example results in the following files being treated as test sources:

  • a.test.scala, since it ends with .test.scala
  • src/test/scala/b.scala, since the path to that directory contains a directory named test

Note that e.scala is not treated as a test source since it lacks a parent directory in its relative path that is exactly named test (the nametest_unit starts with test, but scala-cli only looks for parent directories on the relative path with the exact name test).

scala-cli example/src results in src/test/scala/b.scala being treated as a test file since its relative path (test/scala/b.scala) contains a directory named test.

Conversely, scala-cli example/src/test results in no test sources, since the relative path to b.scala does not contain test (the fact that the directory provided as input is named test does not make its content a test source).

Directives take precedence over file or path names, so using target main can be used to force test/a.scala or a.test.scala to not be treated as tests.

As a rule of thumb, we recommend naming all of your test files with the .test.scala suffix.

Test framework

In order to run tests with a test framework, add the framework dependency to your application. Some of the most popular test frameworks in Scala are:

This example shows how to run an munit-based test suite:

//> using lib "org.scalameta::munit::0.7.27"

class MyTests extends munit.FunSuite {
test("foo") {
assert(2 + 2 == 4)
scala-cli test MyTests.scala
# Compiling project (1 Scala source)
# Compiled project
# MyTests:
# + foo 0.143s

Test arguments

You can pass test arguments to your test framework by passing them after --:

//> using lib "org.scalatest::scalatest::3.2.9"

import org.scalatest._
import org.scalatest.flatspec._
import org.scalatest.matchers._

class Tests extends AnyFlatSpec with should.Matchers {
"A thing" should "thing" in {
assert(2 + 2 == 4)
scala-cli test MyTests.scala -- -oD
# Compiling project (1 Scala source)
# Compiled project
# Tests:
# A thing
# - should thing (22 milliseconds)
# Run completed in 359 milliseconds.
# Total number of tests run: 1
# Suites: completed 1, aborted 0
# Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
# All tests passed.