重申 Spock 在哪里阻止?

Reiterate over Spock where block?

我们使用 Spock 放心地进行 API 测试。我们有一种情况,我们正在从 CSV 文件中读取数据。因此,对于这种情况,让我们假设我们正在读取 10 行数据。对于这 10 行数据,对于给定数量的“公司”,我们有没有办法重复这个单一测试?例如:

@Unroll
def "example test"() {
    when:
    //do something here

    then:
    //check something here

    where:
    row << functionalUtils.getRecordsFromCsv(csvFile)
}

这将 运行 测试 CSV 文件中有多少行,因此如果 CSV 文件中有 10 行,它将 运行 10 次。

但假设我们有 4 家我们支持的公司,它们都具有相同的数据,我们想验证所有 4 家公司是否正确。我们不想将 CSV 文件设为 40 行(相同的 10 行重复 4 次),而是希望对 4 家公司重复此测试 4 次。像

@Unroll
def "example test"() {
    when:
    //do something here

    then:
    //check something here

    where:
    company << ["company a","company b","company c","company d"]
    row << functionalUtils.getRecordsFromCsv(csvFile)
}

我做得比现在更难了吗?这可能吗?我知道这是不正确的,这会出错,我只是想证明我正在尝试做什么。

不知道functionalUtilscsvFile是怎么定义的。我假设前者是一个 @Shared 变量(否则它不能在 where: 块中使用),后者是一个在 where: 块内定义的数据变量。

我正在使用 multi-variable data pipes, a feature which has been around for a couple of years, optionally in combination with multi-variable assignment,这是 Spock 2.0-M3 中引入的一项功能。这个向后兼容的测试版本在 Spock 1.3 和 2.0 中运行:

package de.scrum_master.q66485337

import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll

class MultipleCompaniesCSVTest extends Specification {
  @Shared
  def functionalUtils = new FunctionalUtils()

  @Unroll
  def "company #company, row #row"() {
    expect:
    csvFile.startsWith(company)
    firstName.contains("-$company-")
    lastName.contains("-$company-")
    firstName.endsWith("-$id")
    lastName.endsWith("-$id")

    where:
    [company, csvFile, row] << getRecordsForCompanies("A", "B", "C", "D")
    id = row[0]; firstName = row[1]; lastName = row[2]
    // Since Spock 2.0-M3 you can simplify to:
    // (id, firstName, lastName) = row
  }

  private List<List> getRecordsForCompanies(String... companies) {
    def records = []
    companies.each { company ->
      def csvFile = "${company}.csv"
      functionalUtils.getRecordsFromCsv(csvFile).each { row ->
        records.add([company, csvFile, row])
      }
    }
    records
  }

  static class FunctionalUtils {
    def getRecordsFromCsv(String csvFile) {
      def company = csvFile.replaceFirst("[.]csv$", "")
      // Emulate company-specific CSV file, creating some records
      (1..3).collect { id -> [id, "John-$company-$id", "Doe-$company-$id"] }
    }
  }
}

从 2.0-M3 开始,您可以根据需要将 id = row[0]; firstName = row[1]; lastName = row[2] 简化为 (id, firstName, lastName) = row

顺便说一句,在 Spock 2 中展开是默认的,所以你也可以省略那里的 @Unroll

免责声明:可能有一种更实用的 groovy 方法来为数据管道创建值,无需在闭包或辅助方法中强制修改本地数据结构的状态然后返回最终结果。也许有一些额外的可迭代方法,类似于 permutations()combinations()。如果是这样,我还没有找到它,不是Groovy专家。

如果所有公司的csv文件中的数据相同,你可以在Spock中使用Groovy的combinations() together with multi variable data pipes

where:
[row, company] << [
    functionalUtils.getRecordsFromCsv(csvFile),
    ["company a","company b","company c","company d"]
].combinations()