views:

46

answers:

2

In scalacheck's user guide there is "Generating Case Classes" paragraph. I modified example from it to use regular classes instead of case classes:

import org.scalacheck._
import Gen._
import Arbitrary._

sealed abstract class Tree
object Leaf extends Tree
class Node(left:Tree, rigth:Tree, v:Int) extends Tree

object Main {

  val genLeaf = value(Leaf)
  val genNode = for{
    v <- Arbitrary.arbitrary[Int]
    left <- genTree
    rigth <- genTree
  } yield new  Node(left, rigth, v)

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


  def main(args:Array[String]){    
    println(genTree.sample)
  }
}

It seems everything working but I'm afraid of using this approach in production code before I ask here: is there any pitfalls?

+2  A: 

I see no problem here. The reason why case classes are used in that example is that the Tree shown is an algebraic data type, made possible with case classes. With normal classes, you cannot pattern match on the tree, and, in fact, you won't even be able to get left, right and v without declaring them val.

Daniel
+2  A: 

This should work fine. There's nothing about case classes that are particularly magical about case classes as far as ScalaCheck is concerned. Any old class can get a generator, or even be convertible to Arbitrary.

As far as testing goes, one difference is that every non-case-class tree you generate will be unique, and thus for no two trees you generate will tree1 == tree2. That's different from how it is with case class, which test equality based on value rather than identity. You may need more tests to handle issues with aliasing that become possible when you have identity-based rather than value-based equality.

Dave Griffith