是否有任何方便的方法对多个数据集执行测试 - 就像 JUnit 的参数化测试一样?
ScalaTest 1.5 引入了测试多个数据集的功能。
您混合(或导入)
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 个成员)。第一个元组都是字符串,它们定义了列的名称。随后的元组各自定义一行数据。您可以在元组中放置任何类型,但通常每列都包含相同的类型。不过,如果您愿意,您可以拥有可以包含任何内容的 Any 类型的列。您可以拥有包含 1 到 22 列的表格。如果您需要超过 22 列(Scala 中的最大元组大小当前为 22),您可以做的是在一列或多列中使用复合类型。
一旦你有了桌子,你可以用
forAll
来检查它们,如下所示:
forAll (examples) { (a, b, c, d) =>
a + b + c + d should equal (4)
}
forAll
采用两个参数列表。第一个是表,第二个是“属性函数”,它表达的东西对于表的每一行都应该是正确的。 forAll
将获取表格的每一行(当然,跳过列名称的标题行)并确保属性成立。如果没有,您会收到一条不错的错误消息,说明表的哪一行失败、指定列的值是什么等等。
A
Table
是数据元组的 Seq
,因此您也可以像使用 Seq
一样使用它。例如,您可以获得 Seq
的 Option[Exception]
指示哪些行失败,如下所示:
for ((a, b, c, d) <- examples) yield {
failureOf { a + b + c + d should equal (4) }
}
结果
Seq
对于表中的每一行数据都包含一个 Option
,如果该行的属性通过,则为 None
,如果属性失败,则为 Some[Exception]
。 Some
中的异常包含有关失败的所有详细信息。
数据驱动测试的另一种可能性是使用以下语法:
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
。
共享测试可能会让您感兴趣。它们允许您定义一些测试集,如以下堆栈示例所示:
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是参数化的测试集,您可以将其与要测试的不同数据集一起使用。