我正在为一些产生Excel文件(二进制)的代码编写JUnit测试。我有另一个包含我的预期输出的Excel文件。将实际文件与预期文件进行比较的最简单方法是什么?
当然我可以自己编写代码,但我想知道在可信第三方库(例如Spring或Apache Commons)中是否存在已经执行此操作的现有方法。
答案 0 :(得分:12)
您可以考虑使用我的项目simple-excel,它提供了一堆Hamcrest Matchers来完成这项工作。
当您执行以下操作时,
assertThat(actual, WorkbookMatcher.sameWorkbook(expected));
你会看到,例如,
java.lang.AssertionError:
Expected: entire workbook to be equal
but: cell at "C14" contained <"bananas"> expected <nothing>,
cell at "C15" contained <"1,850,000 EUR"> expected <"1,850,000.00 EUR">,
cell at "D16" contained <nothing> expected <"Tue Sep 04 06:30:00">
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
这样,您可以在自动化测试中运行它,并在开发过程中获得有意义的反馈。
了解更多相关信息答案 1 :(得分:8)
这是我最终做的事情(由DBUnit完成繁重的工作):
/**
* Compares the data in the two Excel files represented by the given input
* streams, closing them on completion
*
* @param expected can't be <code>null</code>
* @param actual can't be <code>null</code>
* @throws Exception
*/
private void compareExcelFiles(InputStream expected, InputStream actual)
throws Exception
{
try {
Assertion.assertEquals(new XlsDataSet(expected), new XlsDataSet(actual));
}
finally {
IOUtils.closeQuietly(expected);
IOUtils.closeQuietly(actual);
}
}
这会比较两个文件中的数据,不存在任何可能不同的无关元数据的漏报风险。希望这有助于某人。
答案 2 :(得分:6)
使用一些校验和(如MD5)或只读取两个文件,可以轻松完成简单的文件比较。
然而,由于Excel文件包含大量元数据,因此James Burgess指出,这些文件可能永远不会是逐字节相同的。 因此,您需要对您的测试进行另一种比较。
我建议以某种方式从Excel文件生成“规范”表单,即读取生成的Excel文件并将其转换为更简单的格式(CSV或类似的东西),这只会保留您要检查的信息。然后你可以使用“规范形式”来比较你的预期结果(当然也是规范形式)。
Apache POI可能对阅读文件很有用。
BTW:读取整个文件以检查其正确性通常不会被视为单元测试。这是一次整合测试......答案 3 :(得分:4)
我需要做类似的事情,并且已经在我的项目中使用Apache POI library来创建Excel文件。所以我选择使用包含的ExcelExtractor接口将两个工作簿导出为一串文本,并断言字符串相等。 HSSF for .xls以及XSSF for .xlsx都有实现。
转储到字符串:
XSSFWorkbook xssfWorkbookA = ...;
String workbookA = new XSSFExcelExtractor(xssfWorkbookA).getText();
ExcelExtractor有一些选项可以包含字符串转储中的所有内容。我发现它有包含工作表名称的有用默认值。此外,它还包括单元格的文本内容。
答案 4 :(得分:2)
您可以使用javaxdelta来检查这两个文件是否相同。它可以从这里获得:
答案 5 :(得分:2)
我找到的最简单方法是使用Tika。 我这样用它:
private void compareXlsx(File expected, File result) throws IOException, TikaException {
Tika tika = new Tika();
String expectedText = tika.parseToString(expected);
String resultText = tika.parseToString(result);
assertEquals(expectedText, resultText);
}
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>1.13</version>
<scope>test</scope>
</dependency>
答案 6 :(得分:0)
刚刚发现公共事物中有一些东西 - FileUtils。谢谢你的其他答案。
答案 7 :(得分:0)
请查看the site以比较二进制文件http://www.velocityreviews.com/forums/t123770-re-java-code-for-determining-binary-file-equality.html
虎
答案 8 :(得分:0)
您可以使用Beyond Compare 3,它可以从命令行启动,并支持不同的方式来比较Excel文件,包括:
答案 9 :(得分:0)
仅测试Kotlin中第一张工作表的内容(可以轻松转换为Java)。
private fun checkEqualityExcelDocs(doc : XSSFWorkbook, doc1 : XSSFWorkbook) : Boolean{
val mapOfCellDoc = doc.toList().first().toList().flatMap { row -> row.map { Pair(PivotExcelCreator.IndexInThePivotTable(it.rowIndex,it.columnIndex),it.stringCellValue) }}.toMap()
val mapOfCellDoc1 = doc1.toList().first().toList().flatMap { row -> row.map { Pair(PivotExcelCreator.IndexInThePivotTable(it.rowIndex,it.columnIndex),it.stringCellValue) }}.toMap()
if(mapOfCellDoc.size == mapOfCellDoc1.size){
return mapOfCellDoc.entries.all { mapOfCellDoc1.containsKey(it.key) && mapOfCellDoc[it.key] == mapOfCellDoc1[it.key]}
}
return false
}
data class IndexInThePivotTable(val row: Int, val col: Int)
并在代码中添加断言
assertTrue(checkEqualityExcelDocs(expected, actual), "Docs aren't equal!")
如您所见,doc.toList().first()
仅会占用文档的第一张纸,如果您需要比较每张纸或分别更改一点代码。
同样,不要考虑空字符串单元格是一个很好的主意,我不需要此功能(同样,如果需要,只需添加此部分)。
这也可能是有用的信息
//first doc I've got from outputstream such way
val out = ByteArrayOutputStream()
//some method which writes excel to outputstream
val firstDoc = XSSFWorkbook(ByteArrayInputStream(out.toByteArray()))
和文件中的第二个文档与
进行比较val secondDoc = XSSFWorkbook(Test::class.java.getClassLoader().getResource("yourfile.xlsx").path)
答案 10 :(得分:-1)
也许......比较每个文件的MD5摘要?我确信有很多方法可以做到这一点。你可以打开两个文件并比较每个字节。
编辑:James说明了XLS格式在元数据方面可能存在差异。也许你应该使用你用来生成xls文件的相同界面打开它们并比较单元格到单元格的值?