Testing in Scala Testing in Scala Concepts: Types of Tests Technology Business Global Local Unit Integration Functional Acceptance Unit Tests Check very specific functionality of your code Assumes everything else works (mocking) Test one specific/technical thing e.g. test your Hadoop job locally, given money in DKK, currency conversion to EUR is called once Integration Tests Check that all components work together Includes real components, databases, files, etc. Test the connectivity of components e.g. run a job on a development Hadoop cluster, given sample data expected output is written Functional Tests Test your product against the functionality you developed Use real components, real data E.g. run job on a live cluster, given a days worth of data the output is correct (as expected according to specification) Acceptance Tests Final tests performed by your client before âaccepting the productâ Real components, real data, output is correct, performance is acceptable, client is happy Concepts: Testing Styles TDD: Test Driven Development BDD: Behavior Driven Development Test Driven Development Write an interface (trait) for the behavior Write an empty implementation Write your unit tests Make the code compile and tests fail Correct the implementation Make the tests pass ! Behavior Driven Development Same idea, just write more functional tests (define behavior) Testing in Scala For every class in src/main/scala write a test class in src/test/scala Test classes ~ Test suites Methods ~ Tests Run the suit and see the output Testing Libraries/Frameworks Java: JUnit, TestNG (can be used with scala) Scala: ScalaTest, Specs2 Mocking: ScalaMock, EasyMock, JMock, Mockito Property Testing: ScalaCheck UI Testing: Selenium Very similar to Specs2, maybe more flexible, mainly choice of taste Integrates with sbt, IntelliJ Integrates with Mockito, ScalaCheck libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.1" % "test" Using ScalaTest 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") { intercept[NoSuchElementException] { Set.empty.head } } } Style Traits ScalaTest allows you to mix in a testing style you like: FunSuite FlatSpec FunSpec WordSpec PropSpec etc. http://www.scalatest.org/user_guide/selecting_a_style FunSuite FlatSpec WordSpec FeatureSpec Testing Styles ScalaTest recommends having an abstract class with the specs and other traits you like package com.mycompany.myproject import org.scalatest._ abstract class UnitSpec extends FlatSpec with Matchers with OptionValues with Inside with Inspectors package com.mycompany.myproject import org.scalatest._ class MySpec extends UnitSpec { // Your tests here } Fixtures Your tests may need some setting up and tearing down ScalaTest has many ways of doing this http://www.scalatest.org/user_guide/sharing_fixtures Matchers ScalaTest has lots of syntactic sugar to express your desires result should equal (3) result should have size 10 string should fullyMatch regex """(-)?(\d+)(\.\d*)?""" result1 should not be an [Orangutan] sevenDotOh should equal (6.9 +- 0.2) "howdy" should contain oneOf ('a', 'b', 'c', 'd') (Array("Doe", "Ray", "Me") should contain oneOf ("X", "RAY", "BEAM")) (after being lowerCased) List(0, 1, 2, 2, 99, 3, 3, 3, 5) should contain inOrder (1, 2, 3) map should (contain key ("two") and not contain value (7)) This is Scala Code !! Mocking You should always code against interfaces (traits) If you do, testing is easier, since you can mock your dependencies! val m = mock[Turtle] m.expects.forward(10.0) twice m1 returns 42 m2 expects ("this", "that") returning "the other" Property Based Testing New and exciting way of testing your code! Instead of examples, you specify properties (higher order testing!) E.g. when you concatenate two lists, new lengths is sum of lengths ScalaCheck then generates random inputs and runs many tests This can catch MANY corner cases you never expect! ScalaCheck import org.scalacheck.Gen val propConcatLists = forAll { (l1: List[Int], l2: List[Int]) => l1.size + l2.size == (l1 ::: l2).size } + OK, passed 100 tests. val propSqrt = forAll { (n: Int) => scala.math.sqrt(n*n) == n } ! Falsified after 1 passed tests: > -1 ScalaCheck: Generators val genLeaf = value(Leaf) val genNode = for { v