Skip to content

Commit

Permalink
Arbitrary section (#5)
Browse files Browse the repository at this point in the history
* Adds Arbitrary section

* Includes the tests for arbitrary section
  • Loading branch information
Fede Fernández committed Jul 11, 2016
1 parent 3b148d5 commit c1995eb
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 0 deletions.
96 changes: 96 additions & 0 deletions src/main/scala/scalachecklib/ArbitrarySection.scala
@@ -0,0 +1,96 @@
package scalachecklib

import org.scalatest.Matchers
import org.scalatest.prop.Checkers

/** ==The `arbitrary` Generator
*
* There is a special generator, `org.scalacheck.Arbitrary.arbitrary`, which generates arbitrary values of any
* supported type.
*
* {{{
* val evenInteger = Arbitrary.arbitrary[Int] suchThat (_ % 2 == 0)
* val squares = for {
* xs <- Arbitrary.arbitrary[List[Int]]
* } yield xs.map(x => x*x)
* }}}
*
* The `arbitrary` generator is the generator used by ScalaCheck when it generates values for ''property'' parameters.
* Most of the times, you have to supply the type of the value to `arbitrary`, like above, since Scala often can't
* infer the type automatically. You can use `arbitrary` for any type that has an implicit `Arbitrary` instance.
* As mentioned earlier, ScalaCheck has default support for common types, but it is also possible to define your own
* implicit `Arbitrary` instances for unsupported types. See the following implicit Arbitrary definition for booleans,
* that comes from the ScalaCheck implementation.
*
* {{{
* implicit lazy val arbBool: Arbitrary[Boolean] = Arbitrary(oneOf(true, false))
* }}}
*
* @param name arbitrary
*/
object ArbitrarySection extends Checkers with Matchers with org.scalaexercises.definitions.Section {

import GeneratorsHelper._

/** Let's see an example where we're defining an `implicit` `arbitrary` instance for `Char`
*/
def implicitArbitraryChar(res0: Seq[Char]) = {

import org.scalacheck.Arbitrary
import org.scalacheck.Gen
import org.scalacheck.Prop.forAll

implicit lazy val myCharArbitrary = Arbitrary(Gen.oneOf('A', 'E', 'I', 'O', 'U'))

val validChars: Seq[Char] = res0

check(forAll { c: Char =>
validChars.contains(c)
})
}

/** This becomes more useful when we're dealing with our own data types.
* We'll use the case class defined in the ''Generators Section'':
*
* {{{
* case class Foo(intValue: Int, charValue: Char)
* }}}
*
* Having an implicit `def` or `val` of our data type in the scope allow us to use the `forAll` method without
* specifying the ''generator''
*/
def implicitArbitraryCaseClass(res0: Boolean) = {

import org.scalacheck.Arbitrary
import org.scalacheck.Gen
import org.scalacheck.Prop.forAll

val fooGen = for {
intValue <- Gen.posNum[Int]
charValue <- Gen.alphaChar
} yield Foo(intValue, charValue)

implicit lazy val myFooArbitrary = Arbitrary(fooGen)

check(forAll { foo: Foo =>
(foo.intValue < 0) == res0 && !foo.charValue.isDigit
})
}

/** The `Arbitrary.arbitrary` method also returns a `Gen` object.
*/
def useArbitraryOnGen(res0: Int) = {

import org.scalacheck.Arbitrary
import org.scalacheck.Gen.listOfN
import org.scalacheck.Prop.forAll

val genEightBytes = listOfN(8, Arbitrary.arbitrary[Byte])

check(forAll(genEightBytes) { list =>
list.size == res0
})

}

}
42 changes: 42 additions & 0 deletions src/test/scala/exercises/scalachecklib/ArbitrarySpec.scala
@@ -0,0 +1,42 @@
package exercises.scalachecklib

import org.scalacheck.Shapeless._
import org.scalatest.Spec
import org.scalatest.prop.Checkers
import shapeless.HNil

import scalachecklib.ArbitrarySection

class ArbitrarySpec extends Spec with Checkers {

def `implicit arbitrary char` = {

check(
Test.testSuccess(
ArbitrarySection.implicitArbitraryChar _,
Seq('A', 'E', 'I', 'O', 'U') :: HNil
)
)
}

def `implicit arbitrary case class` = {

check(
Test.testSuccess(
ArbitrarySection.implicitArbitraryCaseClass _,
false :: HNil
)
)
}

def `arbitrary on gen` = {

check(
Test.testSuccess(
ArbitrarySection.useArbitraryOnGen _,
8 :: HNil
)
)
}

}

0 comments on commit c1995eb

Please sign in to comment.