Scala Tutorial 1

4 minute read

What does the scala project looks like?

By default, sbt follows Maven project layout i.e. Scala source files are placed inside src/main/scala and test source files are placed inside src/test/scala scala-project-structure

  • build.sbt

    Setting dependency, project configuration, task, scalac options, and so on.

  • plugin.sbt

    Setting the plugin of this project

  • build.properties

    Setting the sbt version

  • Dependencies.scala

    Define the custom task or configuration

How to create a scala project?

  • Copy

    Copy an exsiting project, then modify the build.sbt, plugin.sbt, build.properties to use your project configuration

  • Shell

    Generate an universal project structure by shell script, here is an example

  • Giter8

    sbt support Giter8 template, we can generate an project structure from an template

    sbt new sjmyuan/scala-seed.g8
    

    For more template, please visit the Giter8 wiki

How to config project?

:= is a function defined in the sbt library. It is used to define a setting that overwrites any previous value without referring to other settings.

sbt-overriding-values

  • Common options

    name := "tasky"
    version := "0.1.0"
    scalaVersion := "2.11.6"
    sbtVersion := "0.13.8"
    
  • scala compiler options

    scalacOptions ++= Seq("-feature", "-language:_", "-unchecked", "-deprecation", "-encoding", "utf8")
    

You can find all the options by following command

sbt settings

How to add dependency?

Dependency has following format in which the configuration is optional:

groupID % artifactID % version % configuration

We can add dependency like this:

sbt-appending-settings-1 sbt-appending-settings-2

libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.6" % "test" // add single dependency
libraryDependencies ++= Seq(
  "com.typesafe.slick" %% "slick"                   % "2.1.0",
  "net.databinder"     %% "unfiltered-netty-server" % "0.8.4")           // add multiple dependencies

How to add plugin?

Add following settings into plugins.sbt

addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.7.4")

How to add another repository?

resolvers += "Scalaz Bintray Repo" at "http://dl.bintray.com/scalaz/releases"

How to define tasks?

  • Defination
val gitCommitCountTask = taskKey[String]("Prints commit count of the current branch")
gitCommitCountTask := {
  val branch = Process("git symbolic-ref -q HEAD").lines.head.replace("refs/heads/","")
  val commitCount = Process(s"git rev-list --count $branch").lines.head
  println(s"total number of commits on [$branch]: $commitCount")
  commitCount
  }
  • Depend other task, just use other task key like a function
val logTask = taskKey[String]("log the commit count")
gitCommitCountTask := {
  val commitCount = gitCommitCountTask.value
  println(s"Info: $commitCount")
  ""
  }

You can find all the task by following command

sbt tasks

How to publish package?

sbt build
sbt test
sbt run
sbt package

How to write main method?

  • App trait

    object Hello extends Greeting with App {
      println(greeting)
    }
    
  • Object main method

    object Hello1 extends Greeting {
      def main(args:Array[String]): Unit = {
        println(greeting)
      }
    }
    

How to write test?

  • FunSuite

    import org.scalatest.FunSuite
    class SetSuite extends FunSuite {
      test("An empty Set should have size 0") {
        assert(Set.empty.size == 0)
      }
    
      test("Invoking head on an empty Set should produce NoSuchElementException") {
        assertThrows[NoSuchElementException] {
          Set.empty.head
        }
      }
    }
    
  • FlatSpec

    import org.scalatest.FlatSpec
    class SetSpec extends FlatSpec {
      "An empty Set" should "have size 0" in {
        assert(Set.empty.size == 0)
      }
    
      it should "produce NoSuchElementException when head is invoked" in {
        assertThrows[NoSuchElementException] {
          Set.empty.head
        }
      }
    }
    
  • FunSpec

    import org.scalatest.FunSpec
    class SetSpec extends FunSpec {
      describe("A Set") {
        describe("when empty") {
          it("should have size 0") {
            assert(Set.empty.size == 0)
          }
          it("should produce NoSuchElementException when head is invoked") {
            assertThrows[NoSuchElementException] {
              Set.empty.head
            }
          }
        }
      }
    }
    
  • WordSpec

    import org.scalatest.WordSpec
    
    class SetSpec extends WordSpec {
      "A Set" when {
        "empty" should {
          "have size 0" in {
            assert(Set.empty.size == 0)
          }
          "produce NoSuchElementException when head is invoked" in {
            assertThrows[NoSuchElementException] {
              Set.empty.head
            }
          }
        }
      }
    }
    
  • FreeSpec

    import org.scalatest.FreeSpec
    
    class SetSpec extends FreeSpec {
      "A Set" - {
        "when empty" - {
          "should have size 0" in {
            assert(Set.empty.size == 0)
          }
          "should produce NoSuchElementException when head is invoked" in {
            assertThrows[NoSuchElementException] {
              Set.empty.head
            }
          }
        }
      }
    }
    
  • PropSpec

    import org.scalatest._import
    
    prop._import scala.collection.immutable._
    
    class SetSpec extends PropSpec with TableDrivenPropertyChecks with Matchers {
      val examples = Table("set", BitSet.empty, HashSet.empty[Int], TreeSet.empty[Int])
      property("an empty Set should have size 0") {
        forAll(examples) { set => set.size should be(0) }
      }
      property("invoking head on an empty set should produce NoSuchElementException") {
        forAll(examples) { set => a[NoSuchElementException] should be thrownBy {
          set.head
        }
        }
      }
    }
    
  • FeatureSpec

    import org.scalatest._
    
    class TVSet {
      private var on: Boolean = false
      def isOn: Boolean = on
      def pressPowerButton() {
        on = !on
      }
    }
    
    class TVSetSpec extends FeatureSpec with GivenWhenThen {
      info("As a TV set owner")
      info ("I want to be able to turn the TV on and off")
      info ("So I can watch TV when I want")
      info ("And save energy when I'm not watching TV")
      feature("TV power button") {
        scenario("User presses power button when TV is off") {
          Given("a TV set that is switched off")
          val tv = new TVSet assert (!tv.isOn)
    
          When("the power button is pressed")
          tv.pressPowerButton()
    
          Then("the TV should switch on")
          assert (tv.isOn)
        }
        scenario("User presses power button when TV is on") {
          Given("a TV set that is switched on")
          val tv = new TVSet tv.pressPowerButton()
          assert (tv.isOn)
    
          When("the power button is pressed")
          tv.pressPowerButton()
    
          Then("the TV should switch off")
          assert (!tv.isOn)
        }
      }
    }
    
  • RefSpec (JVM only)

    import org.scalatest.refspec.RefSpec
    
    class SetSpec extends RefSpec {
    
      object `A Set` {
    
        object `when empty` {
          def `should have size 0` {
            assert(Set.empty.size == 0)
          }
    
          def `should produce NoSuchElementException when head is invoked` {
            assertThrows[NoSuchElementException] {
              Set.empty.head
            }
          }
        }
    
      }
    
    }
    

Updated:

Comments