In this section you’ll see two tools that are commonly used in Scala projects:
We’ll start by showing how to use sbt to build your Scala projects, and then we’ll show how to use sbt and ScalaTest together to test your Scala projects.
If you want to learn about tools to help you migrate your Scala 2 code to Scala 3, see our Scala 3 Migration Guide.
Building Scala projects with sbt
You can use several different tools to build your Scala projects, including Ant, Maven, Gradle, Mill, and more. But a tool named sbt was the first build tool that was specifically created for Scala.
To install sbt, see its download page or our Getting Started page.
Creating a “Hello, world” project
You can create an sbt “Hello, world” project in just a few steps. First, create a directory to work in, and move into that directory:
$ mkdir hello
$ cd hello
In the directory hello
, create a subdirectory project
:
$ mkdir project
Create a file named build.properties in the directory project
, with
the following content:
sbt.version=1.6.1
Then create a file named build.sbt in the project root directory that contains this line:
scalaVersion := "3.5.2"
Now create a file named something like Hello.scala—the first part of the name doesn’t matter—with this line:
@main def helloWorld = println("Hello, world")
That’s all you have to do.
You should have a project structure like the following:
$ tree
.
├── build.sbt
├── Hello.scala
└── project
└── build.properties
Now run the project with this sbt
command:
$ sbt run
You should see output that looks like this, including the "Hello, world"
from your program:
$ sbt run
[info] welcome to sbt 1.5.4 (AdoptOpenJDK Java 11.x)
[info] loading project definition from project ...
[info] loading settings for project from build.sbt ...
[info] compiling 1 Scala source to target/scala-3.0.0/classes ...
[info] running helloWorld
Hello, world
[success] Total time: 2 s
The sbt launcher—the sbt
command-line tool—loads the version of sbt set in the file project/build.properties, which loads the version of the Scala compiler set in the file build.sbt, compiles the code in the file Hello.scala, and runs the resulting bytecode.
When you look at your directory, you’ll see that sbt has a directory named target. These are working directories that sbt uses.
As you can see, creating and running a little Scala project with sbt takes just a few simple steps.
Using sbt with larger projects
For a little project, that’s all that sbt requires to run. For larger projects that require many source code files, dependencies, or sbt plugins, you’ll want to create an organized directory structure. The rest of this section demonstrates the structure that sbt uses.
The sbt directory structure
Like Maven, sbt uses a standard project directory structure. A nice benefit of that is that once you’re comfortable with its structure, it makes it easy to work on other Scala/sbt projects.
The first thing to know is that underneath the root directory of your project, sbt expects a directory structure that looks like this:
.
├── build.sbt
├── project/
│ └── build.properties
├── src/
│ ├── main/
│ │ ├── java/
│ │ ├── resources/
│ │ └── scala/
│ └── test/
│ ├── java/
│ ├── resources/
│ └── scala/
└── target/
You can also add a lib directory under the root directory if you want to add unmanaged dependencies—JAR files—to your project.
If you’re going to create a project that has Scala source code files and tests, but won’t be using any Java source code files, and doesn’t need any “resources”—such as embedded images, configuration files, etc.—this is all you really need under the src directory:
.
└── src/
├── main/
│ └── scala/
└── test/
└── scala/
“Hello, world” with an sbt directory structure
Creating this directory structure is simple. There are tools to do this for you, but assuming that you’re using a Unix/Linux system, you can use these commands to create your first sbt project directory structure:
$ mkdir HelloWorld
$ cd HelloWorld
$ mkdir -p src/{main,test}/scala
$ mkdir project target
When you run a find .
command after running those commands, you should see this result:
$ find .
.
./project
./src
./src/main
./src/main/scala
./src/test
./src/test/scala
./target
If you see that, you’re in great shape for the next step.
There are other ways to create the files and directories for an sbt project. One way is to use the
sbt new
command, which is documented here on scala-sbt.org. That approach isn’t shown here because some of the files it creates are more complicated than necessary for an introduction like this.
Creating a first build.sbt file
At this point you only need two more things to run a “Hello, world” project:
- A build.sbt file
- A Hello.scala file
For a little project like this, the build.sbt file only needs a scalaVersion
entry, but we’ll add three lines that you commonly see:
name := "HelloWorld"
version := "0.1"
scalaVersion := "3.5.2"
Because sbt projects use a standard directory structure, sbt can find everything else it needs.
Now you just need to add a little “Hello, world” program.
A “Hello, world” program
In large projects, all of your Scala source code files will go under the src/main/scala and src/test/scala directories, but for a little sample project like this, you can put your source code file in the root directory of your project. Therefore, create a file named HelloWorld.scala in the root directory with these contents:
@main def helloWorld = println("Hello, world")
That code defines a Scala 3 “main” method that prints the "Hello, world"
when it’s run.
Now, use the sbt run
command to compile and run your project:
$ sbt run
[info] welcome to sbt
[info] loading settings for project ...
[info] loading project definition
[info] loading settings for project root from build.sbt ...
[info] Compiling 1 Scala source ...
[info] running helloWorld
Hello, world
[success] Total time: 4 s
The first time you run sbt
it downloads everything it needs, and that can take a few moments to run, but after that it gets much faster.
Also, once you get this first step working, you’ll find that it’s much faster to run sbt interactively.
To do that, first run the sbt
command by itself:
$ sbt
[info] welcome to sbt
[info] loading settings for project ...
[info] loading project definition ...
[info] loading settings for project root from build.sbt ...
[info] sbt server started at
local:///${HOME}/.sbt/1.0/server/7d26bae822c36a31071c/sock
sbt:hello-world> _
Then inside this sbt shell, execute its run
command:
sbt:hello-world> run
[info] running helloWorld
Hello, world
[success] Total time: 0 s
There, that’s much faster.
If you type help
at the sbt command prompt you’ll see a list of other commands you can run.
But for now, just type exit
(or press CTRL-D
) to leave the sbt shell.
Using project templates
Manually creating the project structure can be tedious. Thankfully, sbt can create it for you, based on a template.
To create a Scala 3 project from a template, run the following command in a shell:
$ sbt new scala/scala3.g8
Sbt will load the template, ask some questions, and create the project files in a subdirectory:
$ tree scala-3-project-template
scala-3-project-template
├── build.sbt
├── project
│ └── build.properties
├── README.md
└── src
├── main
│ └── scala
│ └── Main.scala
└── test
└── scala
└── Test1.scala
If you want to create a Scala 3 project that cross-compiles with Scala 2, use the template
scala/scala3-cross.g8
:$ sbt new scala/scala3-cross.g8
Learn more about sbt new
and project templates in the documentation of sbt.
Other build tools for Scala
While sbt is widely used, there are other tools you can use to build Scala projects:
Coursier
In a related note, Coursier is a “dependency resolver,” similar to Maven and Ivy in function. It’s written from scratch in Scala, “embraces functional programming principles,” and downloads artifacts in parallel for rapid downloads. sbt uses it to handle most dependency resolutions, and as a command-line tool, it can be used to easily install tools like sbt, Java, and Scala on your system, as shown in our Getting Started page.
This example from the launch
web page shows that the cs launch
command can be used to launch applications from dependencies:
$ cs launch org.scalameta::scalafmt-cli:2.4.2 -- --help
scalafmt 2.4.2
Usage: scalafmt [options] [<file>...]
-h, --help prints this usage text
-v, --version print version
more ...
See Coursier’s launch page for more details.
Using sbt with ScalaTest
ScalaTest is one of the main testing libraries for Scala projects. In this section you’ll see the steps necessary to create a Scala/sbt project that uses ScalaTest.
1) Create the project directory structure
As with the previous lesson, create an sbt project directory structure for a project named HelloScalaTest with the following commands:
$ mkdir HelloScalaTest
$ cd HelloScalaTest
$ mkdir -p src/{main,test}/scala
$ mkdir project
2) Create the build.properties and build.sbt files
Next, create a build.properties file in the project/ subdirectory of your project with this line:
sbt.version=1.5.4
Next, create a build.sbt file in the root directory of your project with these contents:
name := "HelloScalaTest"
version := "0.1"
scalaVersion := "3.5.2"
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "3.2.9" % Test
)
The first three lines of this file are essentially the same as the first example.
The libraryDependencies
lines tell sbt to include the dependencies (JAR files) that are needed to include ScalaTest.
The ScalaTest documentation has always been good, and you can always find the up to date information on what those lines should look like on the Installing ScalaTest page.
3) Create a Scala source code file
Next, create a Scala program that you can use to demonstrate ScalaTest. First, create a directory under src/main/scala named math:
$ mkdir src/main/scala/math
----
Then, inside that directory, create a file named MathUtils.scala with these contents:
package math
object MathUtils:
def double(i: Int) = i * 2
That method provides a simple way to demonstrate ScalaTest.
4) Create your first ScalaTest tests
ScalaTest is very flexible, and offers several different ways to write tests.
A simple way to get started is to write tests using the ScalaTest AnyFunSuite
.
To get started, create a directory named math under the src/test/scala directory:
$ mkdir src/test/scala/math
----
Next, create a file named MathUtilsTests.scala in that directory with the following contents:
package math
import org.scalatest.funsuite.AnyFunSuite
class MathUtilsTests extends AnyFunSuite:
// test 1
test("'double' should handle 0") {
val result = MathUtils.double(0)
assert(result == 0)
}
// test 2
test("'double' should handle 1") {
val result = MathUtils.double(1)
assert(result == 2)
}
test("test with Int.MaxValue") (pending)
end MathUtilsTests
This code demonstrates the ScalaTest AnyFunSuite
approach.
A few important points:
- Your test class should extend
AnyFunSuite
- You create tests as shown, by giving each
test
a unique name - At the end of each test you should call
assert
to test that a condition has been satisfied - When you know you want to write a test, but you don’t want to write it right now, create the test as “pending,” with the syntax shown
Using ScalaTest like this is similar to JUnit, so if you’re coming to Scala from Java, hopefully this looks similar.
Now you can run these tests with the sbt test
command.
Skipping the first few lines of output, the result looks like this:
sbt:HelloScalaTest> test
[info] Compiling 1 Scala source ...
[info] MathUtilsTests:
[info] - 'double' should handle 0
[info] - 'double' should handle 1
[info] - test with Int.MaxValue (pending)
[info] Total number of tests run: 2
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 1
[info] All tests passed.
[success] Total time: 1 s
If everything works well, you’ll see output that looks like that. Welcome to the world of testing Scala applications with sbt and ScalaTest.
Support for many types of tests
This example demonstrates a style of testing that’s similar to xUnit Test-Driven Development (TDD) style testing, with a few benefits of the Behavior-Driven Development (BDD) style.
As mentioned, ScalaTest is flexible and you can also write tests using other styles, such as a style similar to Ruby’s RSpec. You can also use mock objects, property-based testing, and use ScalaTest to test Scala.js code.
See the User Guide on the ScalaTest website for more details on the different testing styles that are available.
Where to go from here
For more information about sbt and ScalaTest, see the following resources: