lim*_*imc 4 csv groovy unit-testing opencsv spock
我正在尝试编写一个优雅的Spock规范,该规范将从CSV文件中读取非常大的测试数据,而无需将所有数据加载到内存中.我正在寻找你的反馈,你可能会比我现在拥有的更好.
我们假设我的简化CSV文件如下所示: -
1,2
3,4
5,6
Run Code Online (Sandbox Code Playgroud)
断言是 "column 1" + 1 == "column 2"
我正在使用OpenCSV来进行我的CSV解析,因为实际的CSV文件包含带有双引号和逗号等特殊字符的字符串,以及通过用逗号分割字符串的基本解析,这样就不起作用了.
<dependency>
<groupId>net.sf.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>2.3</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
尝试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
}
}
Run Code Online (Sandbox Code Playgroud)
尝试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()
}
Run Code Online (Sandbox Code Playgroud)
尝试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(...)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这种尝试并不算太糟糕,但我不得不在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()
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
题
我的问题是......你将如何解决这个问题?有没有更好的方法(或更好的CSV库)?我知道Apache Commons CSV可能是我所知道的唯一解析器Iterable,但它已经存在SNAPSHOT了很长时间.
非常感谢.
编写CSVFile实现Iterable<Iterable<String>>(或Iterable<Iterable<Integer>>)的实用程序类.然后用where: [firstNum, secondNum] << new CSVFile("path/to/file").
| 归档时间: |
|
| 查看次数: |
4265 次 |
| 最近记录: |