单元测试 – Spock:从CSV文件中读取测试数据
我正在尝试编写一个优雅的Spock规范,该规范将从CSV文件中读取非常大的测试数据,而无需将所有数据加载到内存中.我正在寻找你的反馈,你可能会比我现在拥有的更好.
我们假设我的简化CSV文件如下所示: – 1,2 3,4 5,6 断言是“第1列”1 ==“第2列” 我正在使用OpenCSV来进行我的CSV解析,因为实际的CSV文件包含带有双引号和逗号等特殊字符的字符串,以及通过用逗号分割字符串的基本解析,这样就不起作用了. <dependency> <groupId>net.sf.opencsv</groupId> <artifactId>opencsv</artifactId> <version>2.3</version> </dependency> 尝试1 我的第一次尝试是遍历CSV并在每一行上执行断言.虽然这种方法有效,但我无法使用@Unroll将每个断言隔离到单独的独立测试中. def "read from csv"() { expect: def reader = new CSVReader(...) def fields while ((fields = reader.readNext()) != null) { def firstNum = Integer.valueOf(fields[0]) def secondNum = Integer.valueOf(fields[1]) firstNum + 1 == secondNum } } 尝试2 这种尝试允许我使用@Unroll,但这需要将整个数据加载到内存中,这是我首先想要避免的. @Unroll def "read from csv"() { expect: Integer.valueOf(firstNum as String) + 1 == Integer.valueOf(secondNum as String) where: [firstNum,secondNum] << new CSVReader(...).readAll() } 尝试3 在阅读http://spock-framework.readthedocs.org/en/latest/data_driven_testing.html#data-pipes之后,我可以创建一个实现Iterable的对象…而Spock只会指示数据提供者只在需要时查询下一个值,这正是我想要的. @Unroll def "read from csv"() { given: CSVParser csvParser = new CSVParser() expect: def fields = csvParser.parseLine(line as String) def firstNum = Integer.valueOf(fields[0]) def secondNum = Integer.valueOf(fields[1]) firstNum + 1 == secondNum where: line << new Iterable() { @Override Iterator iterator() { return new Scanner(...) } } } 这种尝试并不算太糟糕,但是我必须在expect块中进行一些CSV解析看起来很奇怪,这会在这里混淆实际意图,即执行断言. 尝试4 我的最后一次尝试几乎创建了一个迭代器包装器,它将字段作为单独的变量返回,但除非我将Iterable类提取到一个单独的API中,否则代码读起来相当难看. @Unroll def "read from csv"() { expect: Integer.valueOf(firstNum as String) + 1 == Integer.valueOf(secondNum as String) where: [firstNum,secondNum] << new Iterable() { @Override Iterator iterator() { new Iterator() { def reader = new CSVReader(...) def fields @Override boolean hasNext() { fields = reader.readNext() return fields != null } @Override Object next() { return fields } @Override void remove() { throw new UnsupportedOperationException() } } } } } 题 我的问题是……你将如何解决这个问题?有没有更好的方法(或更好的CSV库)?我知道Apache Commons CSV可能是我所知道的唯一可以实现Iterable的解析器,但它已经很长时间以来一直是SNAPSHOT. 非常感谢. 解决方法
编写一个实用程序类CSVFile,它实现了Iterable< Iterable< String>> (或Iterable< Iterable< Integer>>).然后使用where:[firstNum,secondNum]<<新的CSVFile(“path / to / file”).
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |