Search code examples
databasescalatestingscalacheck

Using ScalaCheck to generate database data


Is there a way to generate faked database data using ScalaCheck? For example, if I pump in my database schema definitions to ScalaCheck is there a way it can generate what I need to test each model I have? Is there a way for it to maintain referential integrity?


Solution

  • You will need to manually create generators for the models. You can create an arbitrary instance for any object and class from a generator. For instance:

    case class Hoge(a: String, b: Int) can be easily generated:

    val hogeGen: Generator[Hoge] = for {
      aGen <- arbitrary[String]
      bGen <- arbitrary[Int]
    } yield Hoge(aGen, bGen)
    

    In order to use this automatically in your property test, you will need an implicit arbitrary instance of the generator. I suggest including the type when writing these to avoid issues.

    implicit val arbHoge: Arbitrary[Hoge] = Arbitrary(hogeGen) 
    

    You could also skip the generator step and just write implicit val arbHoge: Arbitrary[Hoge] = Arbitrary(for { ... } yield Hoge(...))

    But if you're dealing with some realtional database, its likely that you'll have nested structures.

    case class Fuga(h: Hoge, i: Int)
    

    Since you have already defined the generator for Hoge, we can write a generator for Fuga the same way.

    val fugaGen: Generator[Fuga] = for {
      hGen <- hogeGen
      iGen <- arbitrary[Int]
    } yield Fuga(hGen, iGen)
    

    You could also use the arbitrary instance of Hoge the same way we used the standard arbitrary integer available in scalacheck with arbitrary[Hoge]

    And one last note, if you are only dealing with very basic structures like Hoge in this example, then you could just use shapeless and skip the manual definitions.