Testing in Scala (II) : Scalacheck

This week, Scalera brings to you the second part of the post that talked about Scala testing frameworks. Even though Scalatest provides a pretty fresh generic focus about generating tests using a wide variety of specs and suites, ScalaCheck allows implementing propery-based tests.

If you want to use it in your SBT project, you just need to add the following dependency:

libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.12.4" % "test"

Property-based tests

Property-based tests, as their name indicates, consist on defining a group of assertions or properties that every instance of our custom datatype must verify.
For instance, if we are testing our custom Car datatype,

case class Car(wheelAmount: Int,speed: Double){

  require(wheelAmount>0,"So, how? tell me how")

  require(speed>=0,"Seriously?Negative speed?")

  def accelerate(): Car = Car(wheelAmount,speed*2)

}

we could define our CarSpec class with the following content:

import org.scalacheck.Properties
import org.scalacheck.Prop.forAll

object CarSpec extends Properties("Car") {

  property("has non negative speed") = forAll { (c: Car) =>
    car.speed >= 0
  }

  property("has at least one wheel") = forAll { (c: Car) =>
    car.wheelAmount > 0
  }

  property("doubles its speed") = forAll { (c: Car) =>
    val newCar = c.accelerate()
    newCar.speed = 2*c.speed
  }

}

As you can see, it’s as easy as defining the name of the properties that must be checked. With ‘forAll‘ assertion, it will be verified that, for all car instances, defined constraints are checked.

Generators

So now, for testing these properties, it’s necessary to generate values (a ‘few’ of them) of Car type. For this task, ScalaCheck generators are in charge. These structures know the way to generate values of a specific type. For example,

import org.scalacheck.Gen

val myStringGen: Gen[String] = Gen.alphaString

val stringSample: Option[String] = myStringGen.sample

If we use the predef alphaString generator, we’ll be able to generate String random values that only contain [a-z].
With generator’s sample method, we’ll obtain a possible String value.

There are many other generic Gen methods that you should check out 🙂

Gen composition

But, what if we want to create generators for custom types, like Car?
A Gen[T] can be compound for generating more complex values. For example:

val carGen: Gen[Car] = for {
  wheels <- Gen.choose(4,8)
  speed  <- Gen.oneOf(0.0,50.0,100.0,120.0)
} yield Car(wheels,speed)

By Using choose[T](min: T,max: T) method, we can generate values between ‘min’ and ‘max’.
And with oneOf[T](elems: T*) method, we can choose an element from the given element sequence.
This way, using the element obtained from the Int generator, and using the other one obtained from the Double generator, we can build a Car. This doesn’t mean that these values are already evaluated. We’re just indicating that, in case we’re requested for a Car, we know how to obtain one.

o7azz

Tip of the iceberg

As you can see, ScalaCheck is a good choice for creating property-based tests, but Gen[T] element, for generating certain-type semi-random values, can be used in other scopes, beside unit testing.
In future posts, we’ll see how to use them for generating big data blocks in stress tests for BigData applications.

Peace out! 🙂

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s