18

我正在为一些生成 Excel 文件(二进制文件)的代码编写 JUnit 测试。我有另一个包含我预期输出的 Excel 文件。将实际文件与预期文件进行比较的最简单方法是什么?

当然我可以自己编写代码,但我想知道在受信任的第三方库(例如 Spring 或 Apache Commons)中是否存在已经这样做的方法。

4

11 回答 11

16

你可以考虑使用我的项目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)

这样,您就可以从您的自动化测试中运行它,并在开发过程中获得有意义的反馈。

您可以在我网站上的这篇文章中阅读更多相关信息

于 2012-09-10T07:21:31.897 回答
9

这是我最终做的事情(由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);
  }
}

这将比较两个文件中的数据,没有任何可能不同的不相关元数据产生误报的风险。希望这可以帮助某人。

于 2009-05-15T07:26:13.873 回答
6

使用一些校验和(如 MD5)或仅读取两个文件可以轻松完成简单的文件比较。

然而,正如 James Burgess 所指出的,由于 Excel 文件包含大量元数据,因此这些文件可能永远不会逐字节完全相同。所以你需要另一种比较来进行测试。

我建议以某种方式从 Excel 文件生成“规范”表单,即读取生成的 Excel 文件并将其转换为更简单的格式(CSV 或类似的格式),这只会保留您要检查的信息。然后您可以使用“规范形式”与您的预期结果进行比较(当然也是规范形式)。

Apache POI可能对读取文件很有用。

顺便说一句:读取整个文件以检查其正确性通常不会被视为单元测试。那是集成测试...

于 2009-05-14T23:51:52.063 回答
5

我需要做类似的事情,并且已经在我的项目中使用Apache POI 库来创建 Excel 文件。所以我选择使用包含的ExcelExtractor接口将两个工作簿导出为文本字符串,并断言这些字符串是相等的。.xls的 HSSF 和.xlsx 的 XSSF 都有实现。

转储到字符串:

XSSFWorkbook xssfWorkbookA = ...;
String workbookA = new XSSFExcelExtractor(xssfWorkbookA).getText();

ExcelExtractor 有一些选项用于字符串转储中应包含的所有内容。我发现它具有包含工作表名称的有用默认值。此外,它还包括单元格的文本内容。

于 2015-08-05T19:07:36.570 回答
3

我发现最简单的方法是使用 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>
于 2016-05-20T13:15:55.647 回答
2

您可以使用 javaxdelta 检查这两个文件是否相同。它可以从这里获得:

http://javaxdelta.sourceforge.net/

于 2009-05-14T23:26:12.513 回答
0

刚刚发现 commons-io 的FileUtils中有一些东西。感谢其他答案。

于 2009-05-14T23:48:49.963 回答
0

请查看该站点以比较二进制文件,http://www.velocityreviews.com/forums/t123770-re-java-code-for-determining-binary-file-equality.html

老虎

于 2009-05-15T02:01:01.127 回答
0

您可以使用Beyond Compare 3,它可以从命令行启动并支持不同的方式来比较 Excel 文件,包括:

  • 将 Excel 工作表与数据库表进行比较
  • 检查所有文本内容
  • 使用一些格式检查文本内容
于 2010-04-26T12:05:21.793 回答
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)
于 2019-05-31T16:26:16.143 回答
-1

也许...比较每个文件的 MD5 摘要?我敢肯定有很多方法可以做到这一点。您可以打开两个文件并比较每个字节。

编辑:James 说明了 XLS 格式在元数据中的差异。也许您应该使用与生成 xls 文件相同的界面来打开它们并比较单元格之间的值?

于 2009-05-14T23:18:06.387 回答