scalac 在 ScalaTest 测试中发现错误的 forAll 方法

标签 scala scalatest scalacheck

我有一个 ScalaTest 2 类,它扩展了 GeneratorDrivenPropertyChecks,还间接扩展了 FeatureSpecMatchers(通过我写的扩展那些的特征两个类)。它有这样的代码:

forAll(mySequence) { myItem =>
  myItem.applicationID should be (foo.applicationID)
}

编译失败,因为 scalac 说:

[error] APISpec.scala:253: value applicationID is not a member of Seq[com.company.Item]
[error]          myItem.applicationID should be (foo.applicationID)
[error]                 ^

事实证明,至少根据 Eclipse Scala IDE,编译器在 GeneratorDrivenpropertyChecks 中将“forAll”解析为表示此方法:

  /**
   * 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
  }

这不是我想在这里使用的 forAll 方法!

这是 ScalaTest 中的错误吗(即这两个方法不应同时命名为 forAll)?

我应该如何调用正确的方法?

最佳答案

Is this a bug in ScalaTest

它演示了方法重载的限制。

an article on selfless traits , Bill Venners 将此模式描述为此类命名冲突的解决方法。

在您的情况下,首选一个重载,因为它是在“派生类”中定义的。

(我认为;我不是这些测试框架的用户,并且生成了其中一个源等,因此测试这不是启动 sbt 并查看代码的简单问题。)

(编辑:scaladoc 说你应该import Inspectors._。也许你希望用 Matchers 继承它,因为它还建议导入它的同伴,虽然这对我不起作用。如果你确实 import Inspectors._,你实际上不能通过导入名称来引发过载。)

(编辑:解释命名位:参见规范第 2 章的开头,其中说名称的绑定(bind)具有优先级,并且您继承的名称比您导入的名称具有更高的优先级。)

无论如何,一种解决方案是重新混入 Inspector,如下所示。

另一种解决方案是通过重命名导入方法:

import Inspectors.{ forAll => iforAll }

尝试选项“-Xprint:typer”、“-Xlog-implicit-conversions”以查看发生了什么很有用。在您的情况下,您的集合通过 ScalaCheck 1.10 中的隐式 View Gen.value 提升为“常量代”。

import org.scalatest._
import org.scalatest.prop._

//class MySpec extends FeatureSpec with Matchers with GeneratorDrivenPropertyChecks

class MySpec extends FeatureSpec with Matchers with GeneratorDrivenPropertyChecks with Inspectors {
  case class Foo(id: Int)
  val items = 1 to 10 map (Foo.apply(_))
  forAll(items) { x => Console println x.id } 
}

object Test extends App {
  case class Foo(id: Int)
  val items = 1 to 10 map (Foo.apply(_))
  val sut = new MySpec
  sut.forAll(items) { x => Console println x.id }
  //sut.forAll[Foo](items) { x => Console println x.i }
}

一些调试输出:

/*

[info] /home/apm/projects/skala-unit-tests/src/test/scala/maqi/MySpec.scala:15: inferred view from scala.collection.immutable.IndexedSeq[maqi.Test.Foo] to org.scalacheck.Gen[?] = scalacheck.this.Gen.value[scala.collection.immutable.IndexedSeq[maqi.Test.Foo]]:(x: scala.collection.immutable.IndexedSeq[maqi.Test.Foo])org.scalacheck.Gen[scala.collection.immutable.IndexedSeq[maqi.Test.Foo]]


> test
[info] Compiling 3 Scala sources to /home/apm/projects/skala-unit-tests/target/scala-2.10/test-classes...
[error] /home/apm/projects/skala-unit-tests/src/test/scala/maqi/MySpec.scala:16: overloaded method value forAll with alternatives:
[error]   (genAndNameA: (org.scalacheck.Gen[maqi.Test.Foo], String),configParams: maqi.Test.sut.PropertyCheckConfigParam*)(fun: maqi.Test.Foo => Unit)(implicit config: maqi.Test.sut.PropertyCheckConfig, implicit shrA: org.scalacheck.Shrink[maqi.Test.Foo])Unit <and>
[error]   (genA: org.scalacheck.Gen[maqi.Test.Foo],configParams: maqi.Test.sut.PropertyCheckConfigParam*)(fun: maqi.Test.Foo => Unit)(implicit config: maqi.Test.sut.PropertyCheckConfig, implicit shrA: org.scalacheck.Shrink[maqi.Test.Foo])Unit <and>
[error]   (nameA: String,configParams: maqi.Test.sut.PropertyCheckConfigParam*)(fun: maqi.Test.Foo => Unit)(implicit config: maqi.Test.sut.PropertyCheckConfig, implicit arbA: org.scalacheck.Arbitrary[maqi.Test.Foo], implicit shrA: org.scalacheck.Shrink[maqi.Test.Foo])Unit <and>
[error]   (fun: maqi.Test.Foo => Unit)(implicit config: maqi.Test.sut.PropertyCheckConfig, implicit arbA: org.scalacheck.Arbitrary[maqi.Test.Foo], implicit shrA: org.scalacheck.Shrink[maqi.Test.Foo])Unit
[error]  cannot be applied to (scala.collection.immutable.IndexedSeq[maqi.Test.Foo])
[error]   sut.forAll[Foo](items) { x => Console println x.i }
[error]             ^
*/

关于scalac 在 ScalaTest 测试中发现错误的 forAll 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20383657/

相关文章:

Scala 3 - 在一阶类型上提取包装器元组和 InverseMap

scala - 无法解析 org.scalatest#scalatest;3.0.1 : not found dependency issue

scala - 假人的 Akka Actors 单元测试

Scala - 最终超时和 Thread.sleep() 之间的区别

scala - Play +specs2+scalacheck?

scala - 如何构建一个 Actor 及其包装器?

scala - 最小重复子串

scala - Scala 中的reduceLeft 和reduceRight 之间的区别是什么?

java - 在 Java 中随机生成*有趣的*字符串

Scalacheck 忽略提供的生成器