I have a ScalaTest 2 class that extends GeneratorDrivenPropertyChecks
, and also indirectly extends FeatureSpec
and Matchers
(via a trait I wrote which extends those two classes). It has code like this in it:
forAll(mySequence) { myItem =>
myItem.applicationID should be (foo.applicationID)
}
This fails to compile because scalac says:
[error] APISpec.scala:253: value applicationID is not a member of Seq[com.company.Item]
[error] myItem.applicationID should be (foo.applicationID)
[error] ^
It turns out that, at least according to Eclipse Scala IDE, the compiler is resolving "forAll" as meaning this method, in GeneratorDrivenpropertyChecks
:
/**
* Performs a property check by applying the specified property check function to arguments
* supplied by the specified generators.
*
* <p>
* Here's an example:
* </p>
*
* <pre class="stHighlight">
* import org.scalacheck.Gen
*
* // Define your own string generator:
* val famousLastWords = for {
* s <- Gen.oneOf("the", "program", "compiles", "therefore", "it", "should", "work")
* } yield s
*
* forAll (famousLastWords) { (a: String) =>
* a.length should equal ((a).length)
* }
* </pre>
*
* @param fun the property check function to apply to the generated arguments
*/
def forAll[A](genA: Gen[A], configParams: PropertyCheckConfigParam*)(fun: (A) => Unit)
(implicit
config: PropertyCheckConfig,
shrA: Shrink[A]
) {
// body omitted
}
which is not the forAll
method I'm wanting to use here!
Is this a bug in ScalaTest (i.e. that the two methods should not both be named forAll
)?
And how should I call the correct method?
It demonstrates the limits of method overloading.
In an article on selfless traits, Bill Venners describes this pattern as a workaround for these sorts of naming collisions.
In your case, one overload is preferred because it is defined in a "derived class".(I think; I'm not a user of these test frameworks and one of the sources is generated, etc, so testing this was not a simple matter of firing up sbt and looking at code.)
(Edit: the scaladoc says you're supposed to
import Inspectors._
. Maybe you expected to inherit it withMatchers
because it also suggests importing its companion, though that doesn't work for me offhandily. If you didimport Inspectors._
, you can't actually induce an overload by importing the name.)(Edit: to explain the naming bit: see the beginning of Ch 2 of the spec, where it says that bindings of names have precedences, and names you inherit have higher precedence than names you import.)
Anyway, one solution is to remix-in
Inspectors
as shown below.The other solution is to import the method with a rename:
It's useful to try options "-Xprint:typer", "-Xlog-implicit-conversions" to see what's happening. In your case, your collection is promoted to a "constant gen" by an implicit view
Gen.value
in ScalaCheck 1.10.Some debug output: