如何将两个ScalaTest TableDrivenPropertyChecks表格合并为一个?
ScalaTest 分表维护输入与预期输出的合并方案
我希望将输入数据和预期输出数据分开维护在两个Table中,再合并为一个Table用于ScalaTest的TableDrivenPropertyChecks测试框架。尝试直接用inputs zip expectedOutputs传递给forAll时无法生效,因为Table的zip结果不符合forAll的参数要求。常规方式是把输入和预期放在同一张Table,但元组过长时可读性差,分开维护更清晰。
解决方案
ScalaTest的forAll期望接收Table类型参数,而inputs zip expectedOutputs会返回IndexedSeq,无法直接使用。我们需要手动将两个Table的列名和行数据合并,构造出一个新的Table。
具体实现代码
import org.scalatest.prop.TableDrivenPropertyChecks._ import org.scalatest.matchers.should.Matchers._ // 定义输入数据表格 val inputs = Table( ("a", "b"), (1, 2), (-1, 2) ) // 定义预期输出表格 val expectedOutputs = Table( ("addition", "subtraction"), (3, -1), (1, -3) ) // 合并输入与输出的列名 val combinedColumns = inputs.headers ++ expectedOutputs.headers // 合并每行的输入与输出数据 val combinedRows = inputs.toSeq.zip(expectedOutputs.toSeq).map { case (inputRow, outputRow) => // 将两个元组的元素拼接为新序列,再转为Tuple (inputRow.productIterator ++ outputRow.productIterator).toTuple } // 构造合并后的测试表格 val combinedTable = Table(combinedColumns, combinedRows: _*) // 执行表驱动测试 forAll(combinedTable) { (a: Int, b: Int, add: Int, sub: Int) => // 示例待测试函数 def sumFn(x: Int, y: Int): Int = x + y def diffFn(x: Int, y: Int): Int = x - y sumFn(a, b) shouldEqual add diffFn(a, b) shouldEqual sub }
复用工具函数
如果需要多次合并不同的输入输出表,可以封装一个工具函数:
import org.scalatest.prop.Table def mergeTables[A <: Product, B <: Product](inputTable: Table[A], outputTable: Table[B]): Table[Product] = { val combinedHeaders = inputTable.headers ++ outputTable.headers val combinedRows = inputTable.toSeq.zip(outputTable.toSeq).map { case (inRow, outRow) => (inRow.productIterator ++ outRow.productIterator).toTuple } Table(combinedHeaders, combinedRows: _*) } // 使用工具函数快速合并 val combinedTable = mergeTables(inputs, expectedOutputs)
关键说明
Table的toSeq方法可以将表格行转为IndexedSeq[Product],方便进行zip操作- 通过
productIterator可以遍历元组的所有元素,实现两个元组的拼接 - 构造新
Table时,需要将合并后的行序列转为可变参数(: _*)以匹配Table的构造参数要求
内容的提问来源于stack exchange,提问作者sahibeast
相关产品推荐
相关产品推荐

