testing in scala. adform research

35
Testing in Scala

Upload: vasil-remeniuk

Post on 15-Jul-2015

117 views

Category:

Technology


0 download

TRANSCRIPT

Testing in Scala

Concepts: Types of Tests

Technology

Business

GlobalLocal

Unit IntegrationFunctional

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 <- arbitrary[Int]

left <- genTree

right <- genTree

} yield Node(left, right, v)

def genTree: Gen[Tree] = oneOf(genLeaf, genNode)

Option[Tree] = Some(Node(Leaf,Node(Node(Node(Node(Node(Node(Leaf,Leaf,-71),Node(Leaf,Leaf,-49),17),Leaf,-20),Leaf,-7),Node(Node(Leaf,Leaf,26),Leaf,-3),49),Leaf,84),-29))

is

AWESOME !!

Scoverage

• Produces test coverage reports

• Measures how many statements are tested

• Only works with Scala 2.11

Testing Scalding Jobs

HOMEWORK: use ScalaTest instead of Specs2

DEMO TIMESlava takes the stage