Generators in ScalaCheck
Learn how to use and compose generators in ScalaCheck.
Automatic generators
We can unleash the full power of property-based testing with automatic generators. Different from table-driven property checking, generator-based tests can benefit from automatic generators of class instances. Normally, such an automatic generation tries to cover all the edge cases of our input domain.
We can’t generate input automatically with ScalaTest alone. In Scala the most popular property-based testing library is ScalaCheck. We’ll add it to our project (line 6).
object Dependencies {object org {object scalatestplus {val `scalacheck-1-17` = "org.scalatestplus" %% "scalacheck-1-17" % "3.2.15.0"}}}
In this lesson, we’ll see how we can leverage ScalaCheck to generate values for us.
Basic generation: the Properties
class
The most basic form of property-based checking in ScalaCheck makes use of the Properties
class. In this case, ScalaTest is not even necessary; we can write a property-based test suite simply by creating a Scala object (not a class—tests won’t run) extending ScalaCheck’s Properties
.
We can start experimenting by writing a specification for the price of a FreeCourse
, even though the logic we’ll be testing is trivial, to say the least.
package mdipirro.educative.io.effectiveunitandintegrationtestinginscala.properties import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.model.v3.{Author, FreeCourse, Lesson} import org.scalacheck.Prop.propBoolean import org.scalacheck.{Prop, Properties} import scala.language.adhocExtensions object FreeCoursePriceSpec extends Properties("A free course"): property("Is always free, no matter the number of lessons") = Prop `forAll` { (t: String, afn: String, aln: String, ts: Set[String]) => (afn.nonEmpty && aln.nonEmpty) ==> { val lessons = ts map Lesson.apply val author = Author(afn, aln) FreeCourse(t, author, lessons, Set.empty).price == 0 } }
As you can see, we defined an object extending the Properties
class of the ScalaCheck library (line 9). The argument of the Properties
constructor is the name of the unit under test. Note that we had to import scala.language.adhocExtensions
(line 7). This is necessary because Properties
is a class and it’s not declared open
. Therefore, in Scala 3, we need that flag to extend it. ...