task-218(离线可收部分): 结果文件格式契约(真实 AppearancePatentSheetBuilder 纯调用:Sheet 名/主表列序(含标题/图片链接/sku)/原因表列/空行产出)+ 8 测试

文件名 <stem>-result.xlsx 与 ZIP 结构由运行时组装/上传环节生成,依赖真实流水线(3+2 约定 env-gated 另行验证)
This commit is contained in:
2026-09-05 09:23:21 +08:00
parent 4735a18390
commit 6bd3e76048
@@ -0,0 +1,110 @@
package com.nanri.aiimage.modules.appearancepatent.service.support;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* task-218(离线可收部分):结果文件格式契约(真实 Sheet builder 纯调用)。
*
* 调 AppearancePatentSheetBuilder 在内存 Workbook 生成 Sheet,断言 Sheet 名、主表列序、
* 原因表列名冻结、空行也能产出(空结果文件);文件名 `<stem>-result.xlsx` 与 ZIP 结构
* 由运行时组装/上传环节生成,依赖真实流水线(env-gated 部分另行验证)。
*/
class AppearancePatentResultFormatTest {
private static Workbook build() {
Workbook wb = new XSSFWorkbook();
AppearancePatentSheetBuilder.buildResultSheet(wb, List.of(), Map.of());
return wb;
}
private static List<String> expectedMainHeaders() {
List<String> headers = new ArrayList<>(AppearancePatentSheetBuilder.RESULT_HEADERS);
headers.add(6, "标题");
headers.add(7, "图片链接");
headers.add(8, "sku");
return headers;
}
@Test
void mainSheetNameFrozen() throws Exception {
try (Workbook wb = build()) {
assertNotNull(wb.getSheet("外观专利检测结果"), "主 Sheet 名应冻结为 外观专利检测结果");
}
}
@Test
void reasonSheetNameFrozen() throws Exception {
try (Workbook wb = build()) {
assertNotNull(wb.getSheet("原因"), "原因 Sheet 名应冻结为 原因");
}
}
@Test
void mainHeaderColumnOrderMatchesContract() throws Exception {
try (Workbook wb = build()) {
Sheet sheet = wb.getSheet("外观专利检测结果");
Row header = sheet.getRow(0);
List<String> actual = new ArrayList<>();
for (int i = 0; i < header.getLastCellNum(); i++) {
actual.add(header.getCell(i).getStringCellValue());
}
assertEquals(expectedMainHeaders(), actual, "主表列序应与 RESULT_HEADERS + 标题/图片链接/sku 一致");
}
}
@Test
void reasonHeaderColumnsFrozen() throws Exception {
try (Workbook wb = build()) {
Sheet reason = wb.getSheet("原因");
Row header = reason.getRow(0);
assertEquals("ASIN", header.getCell(0).getStringCellValue());
assertEquals("外观原因", header.getCell(1).getStringCellValue());
assertEquals("专利原因", header.getCell(2).getStringCellValue());
assertEquals("标题原因", header.getCell(3).getStringCellValue());
}
}
@Test
void emptyRowsStillGenerateSheets() throws Exception {
try (Workbook wb = build()) {
assertNotNull(wb.getSheet("外观专利检测结果"));
assertNotNull(wb.getSheet("原因"));
assertEquals(0, wb.getSheet("外观专利检测结果").getPhysicalNumberOfRows() - 1,
"空行时应仅表头,无数据行抛错");
}
}
@Test
void resultHeadersConstantDefinesBrandColumns() throws Exception {
List<String> headers = AppearancePatentSheetBuilder.RESULT_HEADERS;
assertTrue(headers.contains("品牌") && headers.contains("价格") && headers.contains("结论")
&& headers.contains("状态"), "RESULT_HEADERS 应含 品牌/价格/结论/状态");
}
@Test
void firstColumnIsRowId() throws Exception {
List<String> headers = expectedMainHeaders();
assertEquals("id", headers.get(0), "首列应为 id");
assertEquals("asin", headers.get(1));
}
@Test
void columnCountMatchesContract() throws Exception {
try (Workbook wb = build()) {
int headerCount = wb.getSheet("外观专利检测结果").getRow(0).getLastCellNum();
assertEquals(expectedMainHeaders().size(), headerCount, "列数应与契约表头一致");
}
}
}