10

是否有任何方便的方法对多个数据集执行测试——比如在 JUnit 的参数化测试中?

4

3 回答 3

13

ScalaTest 1.5 中有一个用于测试多个数据集的新功能,您目前可以将其作为快照尝试。它在 scala-tools.org 上发布:

组 id:org.scalatest 工件 id:scalatest 版本:1.5-SNAPSHOT

您混合(或导入)TableDrivenPropertyChecks 的成员,然后您可以像这样定义表:

val examples =
  Table(
    ("a", "b", "c", "d"),
    (  1,   1,   1,   1),
    (  1,   1,   1,   1),
    (  1,   1,   1,   1),
    (  1,   1,   1,   1)
  )

您将元组的 var arg 列表传递给 Table。每个元组必须具有相同的元组,在这种情况下,每个元组都有 4 个元组(4 个成员)。第一个元组是所有字符串,它们定义了列的名称。随后的元组中的每一个都定义了一行数据。您可以在元组中放置任何类型,但通常每列都包含相同的类型。不过,如果您愿意,您可以拥有任何类型的列,其中可以包含任何内容。您可以拥有 1 到 22 列的表格。如果您需要超过 22 列(Scala 中的最大元组大小当前为 22),您可以做的是在一列或多列中使用复合类型。

一旦你有一张桌子,你可以像这样用 forAll 检查它们:

forAll (examples) { (a, b, c, d) =>
  a + b + c + d should equal (4)
}

forAll 采用两个参数列表。第一个是表,第二个是“属性函数”,它表达了对表的每一行都应该为真的东西。forAll 将获取表格的每一行(当然,跳过列名的标题行)并确保该属性成立。如果没有,您会收到一条很好的错误消息,说明表的哪一行失败,命名列的值是什么等。

表是数据元组的 Seq,因此您也可以像 Seq 一样使用它。例如,您可以获得 Option[Exception] 的 Seq,指示哪些行失败,如下所示:

for ((a, b, c, d) <- examples) yield {
  failureOf { a + b + c + d should equal (4) }
}

生成的 Seq 包含表中每一行数据的一个选项,如果为该行传递了属性,则为 None,如果属性失败,则为 Some[Exception]。Some 中的异常包含有关失败的所有详细信息。

于 2011-03-20T19:01:39.060 回答
7

共享测试对您来说可能很有趣。它们允许您定义一些测试集,例如此堆栈示例:

  def nonEmptyStack(stack: Stack[Int], lastItemAdded: Int) {
    "be non-empty" in {
      assert(!stack.empty)
    }
    "return the top item on peek" in {
      assert(stack.peek === lastItemAdded)
    }
    "not remove the top item on peek" in {
      val size = stack.size
      assert(stack.peek === lastItemAdded)
      assert(stack.size === size)
    }
    "remove the top item on pop" in {
      val size = stack.size
      assert(stack.pop === lastItemAdded)
      assert(stack.size === size - 1)
    }
  }

然后在实际规范中,您可以像这样使用它:

behave like nonEmptyStack(stackWithOneItem, lastValuePushed)

因此,换句话说,nonEmptyStack是一组参数化的测试,您可以将其用于要测试的不同数据集。

于 2011-03-20T15:57:27.090 回答
7

数据驱动测试的另一种可能性是使用以下语法:

class SampleTest extends FunSuite {      
  val input = List((1, 1), (4, 2), (9, 3))

  input.foreach{i =>
    test(s"Test of math.sqrt(${i._1})") {
      assert(math.sqrt(i._1) === i._2)
    }
  }
}

测试默认并行执行,除非在 build.sbt 中设置parallelExecution in Test := false

于 2015-03-13T09:05:01.290 回答