使用 ScalaTest 测试多个数据集

发布于 2024-10-23 15:40:58 字数 184 浏览 8 评论 0原文

是否有任何方便的方法使用 ScalaTest 对多个数据集执行测试 - 就像 JUnit 的 参数化测试

Is there any convenient way execute tests on multiple data sets with ScalaTest — like in JUnit's parametrized tests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深府石板幽径 2024-10-30 15:40:58

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 将获取表的每一行(当然,跳过列名称的标题行)并确保该属性成立。如果没有,您会收到一条不错的错误消息,说明表的哪一行失败、指定列的值是什么等等。

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

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

生成的 Seq 包含一个 Option 对于表中的每一行数据,如果该行的属性通过,则为 None;如果属性失败,则为 Some[Exception]Some 中的异常包含有关失败的所有详细信息。

ScalaTest 1.5 introduced the table-driven property checks feature for testing multiple data sets.

You mix in (or import the members of) TableDrivenPropertyChecks, then you can define tables like this:

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

You pass a var arg list of tuples to Table. Each tuple has to have the same arity, in this case each tuple has arity 4 (4 members). The first tuple is all strings, and these define names for the columns. The subsequent tuples each define one row of data. You can put any type in the tuple, but in general each column would contain the same type. Though if you wanted you could have columns of type Any that can contain anything. You can have table with 1 to 22 columns. If you need more than 22 columns (the max tuple size in Scala is currently 22), what you could do is use a compound type in one or more columns.

Once you have a table, you can check them with forAll like this:

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

forAll takes two parameter lists. The first is a table and the second is a "property function," which expresses something that should be true for every row of the table. forAll will take each row of the table (skipping the heading row of column names, of course) and make sure the property holds. If it doesn't, you get a nice error message saying which row of the table failed, what the values of the named columns were, etc.

A Table is a Seq of the data tuples, so you can also use it like a Seq. For example, you could get a Seq of Option[Exception] indicating which rows failed like this:

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

The resulting Seq contains one Option for each row of data in the table, which is a None if the property passed for that row, and Some[Exception] if the property failed. The exception in the Some contains all the details about the failure.

我不是你的备胎 2024-10-30 15:40:58

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

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

Another possibility for data-driven testing is to use the following syntax:

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)
    }
  }
}

Tests by default execute in parallel unless in build.sbt you set parallelExecution in Test := false.

菩提树下叶撕阳。 2024-10-30 15:40:58

共享测试可能会让您感兴趣。它们允许您定义一些测试集,如这个堆栈示例:

  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是参数化的测试集,您可以将其与不同的测试一起使用您想要测试的数据集。

Shared tests can be interesting to you. They allow you to define some set of tests like in this stack example:

  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)
    }
  }

and then in actual spec you can use it like this:

behave like nonEmptyStack(stackWithOneItem, lastValuePushed)

So in other words nonEmptyStack is parametrized set of tests that you can use with different data sets you want to test.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文