Reputation: 591
I have a class that looks like this:
class EpidemySimulator extends Simulator {
...
class Person{
// Implementation
}
}
I want to add an Arbitrary of the inner class Persons so that I can define some properties on the EpidemySimulator class. I thought the companion object can define the necessary implicit Generators needed in order to define properties which will generate objects of type Person.
object EpidemySimulator
{
implicit def arbPerson(implicit sim: EpidemySimulator ) =
Arbitrary(for(n <- Gen.choose(1, roomRows * roomColumns))yield{ new sim.Person(n) })
def propertyOne(sim: EpidemySimulator ) = forAll { person: sim.Person =>
person.row > 0 && person.row < roomRows && person.col > 0 && person.col < roomColumns
}
}
My understanding was that if I provided the implicit function that creates Arbitrary[sim.Person]
given a particular sim:EpidemySimulator
( which is provided implicitly ) then I should be able to create a property as in propertyOne
. However I get a compiler error on the property which says
Multiple markers at this line
- identifier expected but ';' found.
- not enough arguments for method forAll: (implicit p: Boolean => org.scalacheck.Prop, implicit a1: org.scalacheck.Arbitrary[sim.Person],
implicit s1: org.scalacheck.Shrink[sim.Person], implicit pp1: sim.Person => org.scalacheck.Pretty)org.scalacheck.Prop. Unspecified value parameters
a1, s1, pp1.
- could not find implicit value for parameter a1: org.scalacheck.Arbitrary[sim.Person]
- type <error> is not a member of simulations.EpidemySimulator
Any ideas what I'm doing wrong. I want to be able to ultimately:
class EpidemySuite extends FunSuite with Checkers {
test("EpidemySimulator fulfills property one"){
val es = new EpidemySimulator
check( EpidemySimulator.propertyOne(sim) )
}
}
Upvotes: 1
Views: 571
Reputation: 12565
I think the issue is the following: you have provided an implicit to generate an arbitrary EpidemySimulator#Person given an EpidemySimulator.
implicit def arbPerson(implicit sim: EpidemySimulator ) =
Arbitrary(for(n <- Gen.choose(1, roomRows * roomColumns))yield{ new sim.Person(n) })
But in the test for the EpidemySimulator, there is no implicit value of type EpidemySimulator available, so the above implicit for a person can not be used. Making the sim implicit or defining a local implicit of type epidemySimulator should fix the issue
def propertyOne(implicit sim: EpidemySimulator ) = forAll { person: sim.Person =>
person.row > 0 && person.row < roomRows && person.col > 0 && person.col < roomColumns
}
Given that you will probably want to test various properties of an EpidemySimulator, it is probably a good idea to define an implicit epidemySimulator val somewhere in your object.
Note that I only checked these with a scala console session like this:
import org.scalacheck._
import org.scalacheck.Prop.forAll
// define a class with an inner class
class A { class B }
// define an implicit that provides a A#B given an A
implicit def arbAB(implicit a:A) : Arbitrary[a.B] = Arbitrary[a.B] { new a.B }
// the non-working code
def test(a:A) = forAll { x:a.B => true }
<console>:25: error: could not find implicit value for parameter a1: org.scalacheck.Arbitrary[a.B]
def test(a:A) = forAll { x:a.B => true }
^
// making a an implicit works
def test(implicit a:A) = forAll { x:a.B => true }
Upvotes: 1