Further, in our series on Acceptance Test Driven Development, we would look at generating random test values with the ScalaCheck framework. In our last post we looked at, how we make our test logic respect the DRY principle by defining the values in a table. However, in many situations, you would like to generate the values dynamically so that we do not have to fill a lot of values in the table. Let us see how this is done with the help of a library called ScalaCheck

We would change our test case a bit for dynamic value generation. Look at the code sample below

class MultiplicationSpecWithGenerators extends FeatureSpec with GivenWhenThen with GeneratorDrivenPropertyChecks

The important thing to note here is the trait called **GeneratorDrivenPropertyChecks**. This trait facilitates property checks against generated data using ScalaCheck.

In order to include ScalaCheck library in your project, we would need to include the following dependency

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

Let us look at the complete code sample

import org.scalatest.FeatureSpec import org.scalatest.GivenWhenThen import org.scalatest.prop.TableDrivenPropertyChecks import org.scalatest.prop.GeneratorDrivenPropertyChecks import org.scalacheck.Gen import scala.compat.Platform class MultiplicationSpecWithGenerators extends FeatureSpec with GivenWhenThen with GeneratorDrivenPropertyChecks { val validNumberOnes = for (n <- Gen.choose(-10, 300)) yield n val validNumberTwos = for (n <- Gen.choose(10, 15)) yield n feature("Multiplication") { info(" In order to avoid making mistakes") info("As an accountant") info(" I want to multiply numbers") scenario("Multiply two variables") { forAll(validNumberOnes, validNumberTwos, minSuccessful(500), maxDiscarded(30), workers(4)) { (x: Int, y: Int) => given("a variable x with value " + x) and("a variable y with value " + y) when("i multiply " + x +" and " + y) val expectedResult = (x * y) assert((new ActualBusinessImplementation).actualMultiply(x, y) === expectedResult.toInt) then("i get " + expectedResult) } } } } /** * Actual Software Under Test */ class ActualBusinessImplementation{ def actualMultiply(a:Int, b:Int) = a * b }

As you would notice, most of the things are quite the same as in our last example where we were using **TableDrivenPropertyChecks**. The difference being that now, instead of using Table driven values, we end up Generating values.

val validNumberOnes = for (n <- Gen.choose(-10, 300)) yield n val validNumberTwos = for (n <- Gen.choose(10, 15)) yield n

This code generates numbers between the given range. So it is -10 to 300 for validNumberOnes and between 10 to 15 for validNumberTwos.

forAll(validNumberOnes, validNumberTwos, minSuccessful(500), maxDiscarded(30), workers(4)) { (x: Int, y: Int) =>

Trait GeneratorDrivenPropertyChecks contains forAll method that provides various ways to check properties using generated data. Here, we are not only getting values of valiNumberOnes and validNumberTwos but also specifying the configuration parameters like minSuccessful, maxDiscarded and workers

minSuccessful 500 the minimum number of successful property evaluations required for the property to pass maxDiscarded 30 the maximum number of discarded property evaluations allowed during a property check workers 4 specifies the number of worker threads to use during property evaluation

Notice that the software under test in this case is the **ActualBusinessImplementation** class.

When we execute it, the system runs 500 successful tests with various value combinations and hence we know that the result is correct. The output of the evaluation would look something like this.

[info] Given a variable x with value 160 [info] Given a variable x with value 236 [info] And a variable y with value 12 [info] And a variable y with value 12 [info] When i multiply 160 and 12 [info] When i multiply 236 and 12 [info] Then i get 1920 [info] Then i get 560 [info] And a variable y with value 13 [info] Given a variable x with value 62 [info] When i multiply 23 and 13 [info] And a variable y with value 15 [info] When i multiply 62 and 15 [info] Given a variable x with value 149 [info] Then i get 930 [info] And a variable y with value 13 [info] Given a variable x with value 29 [info] When i multiply 149 and 13 [info] And a variable y with value 15 [info] Then i get 1937 [info] When i multiply 29 and 15 [info] Given a variable x with value 105 [info] Then i get 435 ... ...

The ordering of the output looks a little weird because we are running the evaluation with **four** threads. As always the code is present on the Knoldus Github account.

Hence, as we saw it is easy to generate values with ScalaCheck and pass it to our test case. We can also specify the minimum number of generated value test which would need to be performed before we say that our code is good. In a follow up post to this ATDD series, we would look at another interesting candidate which would make life easy for stakeholders and developers. Till then.

“val validNumberOnes = for (n n)”. In this case you can simply write “val validNumberOnes = Gen.choose(-10, 300)”.