Simple Scala project step-by-step
BE AWARE!!! This post refers to an old SBT version, check the new one
Recently I have started a project that will be coded in Scala. Here I leave some instructions for setting up the the scala project that uses sbt for project management and creates unit tests with scalatests. This entry follows the structure of this post but introduces some changes and improvements.
- Install sbt
- Create a new project
$ mkdir test-project $ cd test-project/ $ sbt Project does not exist, create new project? (y/N/s) y Name: TestProject Organization: com.example Version [1.0]: Scala version [2.7.7]: 2.9.0 sbt version [0.7.4]: 0.7.7
- First we need to install a sbt plugin that collects test results and creates a xUnit report for using in a Continuous Integration Server like Jenkins. Details of that plugin can be found here. Create the file project/plugins/TestProjectPlugins.scala that instructs sbt to download the junit_xml_listener plugin.
import sbt._ class TestProjectPlugins(info: ProjectInfo) extends PluginDefinition(info) { val repo = "Christoph's Maven Repo" at "http://maven.henkelmann.eu/" val junitXml = "eu.henkelmann" % "junit_xml_listener" % "0.2" } - Once we have the configuration for getting the plugin, create the project dependencies and include the new listener into the available ones by overriding the defaults. So, create a build configuration file in project/build/TestProject.scala like:
import sbt._ import eu.henkelmann.sbt.JUnitXmlTestsListener class TestProject(info: ProjectInfo) extends DefaultProject(info) { val scalatest = "org.scalatest" %% "scalatest" % "1.6.1" % "test" //create a listener that writes to the normal output directory def junitXmlListener: TestReportListener = new JUnitXmlTestsListener(outputPath.toString) //add the new listener to the already configured ones override def testListeners: Seq[TestReportListener] = super.testListeners ++ Seq(junitXmlListener) } - Now, we have the project setup in place. Let’s write some classes and tests in order to check that everything is OK. First create the class under test in src/main/scala/Calc.scala
package com.example object Calc { def add(x:Int, y:Int) : Int = x + y } - Now, create a test in src/test/scala/CaltTest.scala that assures that the class is working as expected
package com.example.test import com.example.Calc import org.scalatest.Suite class CalcTest extends Suite { def testAddition() { assert(4 === Calc.add(2,2)) } } - Now just test that tests pass by doing
sbt clean-plugins sbt clean sbt update sbt test
you should see something like this:
$ sbt test [info] Building project test 1.0 against Scala 2.9.0 [info] using TestProject with sbt 0.7.7 and Scala 2.7.7 [info] [info] == compile == [info] Source analysis: 0 new/modified, 0 indirectly invalidated, 0 removed. [info] Compiling main sources... [info] Nothing to compile. [info] Post-analysis: 3 classes. [info] == compile == [info] [info] == test-compile == [info] Source analysis: 0 new/modified, 0 indirectly invalidated, 0 removed. [info] Compiling test sources... [info] Nothing to compile. [info] Post-analysis: 1 classes. [info] == test-compile == [info] [info] == copy-test-resources == [info] == copy-test-resources == [info] [info] == copy-resources == [info] == copy-resources == [info] [info] == test-start == [info] == test-start == [info] [info] == com.example.test.CalcTest == [info] CalcTest: [info] - testAddition [info] - testAdditionWithJavaObject [info] == com.example.test.CalcTest == [info] [info] == test-complete == [info] == test-complete == [info] [info] == Test cleanup 1 == [info] Deleting directory /tmp/sbt_b7e36ab4 [info] == Test cleanup 1 == [info] [info] == test-finish == [info] Passed: : Total 2, Failed 0, Errors 0, Passed 2, Skipped 0 [info] [info] All tests PASSED. [info] == test-finish == [info] [info] == test-cleanup == [info] == test-cleanup == [info] [info] == test == [info] == test == [success] Successful. [info] [info] Total time: 1 s, completed 24-ago-2011 15:40:26 [info] [info] Total session time: 2 s, completed 24-ago-2011 15:40:26 [success] Build completed successfully.
The test reports are located in target/scala_*/test-reports/*.xml. I have setup a Mercurial project with all this code for fast start up, check it out here.
@Banooker scalatests 1.3 does not work for Scala 2.9. Try 1.4.1 instead.
@tonicebrian Thanks! I believe this was a binary incompatibility issue, as you pointed out. When I forced everything to 2.7.7 it finally worked!
If you’re using Scala 2.9 the latest ScalaTest version for that is 1.6.1.
@Bill Venners Thanks, I’ve just updated the post and the mercurial template
Tony — did you try it under SBT 0.11.2, and what changes should be made for it? I think nowdays everything moves to 0.11 so we need an update for it.
@Alexy Khrabrov Good point, I’ve just created another post with a minimal Scala and SBT 0.11.2 project. Check it out!!