From ce62d2f353a90b4b9fc9dec45c9820d48ac83049 Mon Sep 17 00:00:00 2001 From: Agent Date: Sat, 6 Jun 2026 12:52:51 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20v1.5.0=20-=20=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BB=A3=E7=A0=81=E3=80=81=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=8A=A5=E5=91=8A=EF=BC=8C=E6=9B=B4=E6=96=B0=20tasks.md=20?= =?UTF-8?q?=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Code/src/test_pinmap.py | 231 +++++++ Releases/pinmap-to-pinlist-v1.3.14.zip | Bin 0 -> 79108 bytes Releases/pinmap-to-pinlist-v1.3.15.zip | Bin 0 -> 157238 bytes Test/fixtures/BallList-Template.xlsx | Bin 0 -> 2542 bytes Test/fixtures/BallMAP-Template.xlsx | Bin 0 -> 2538 bytes Test/fixtures/template_corrupt.xlsx | 1 + Test/fixtures/template_minimal.xlsx | Bin 0 -> 2331 bytes Test/fixtures/template_narrow.xlsx | Bin 0 -> 2381 bytes Test/run_tests.py | 361 +++++++++- Test/test_plan_v1.5.md | 680 +++++++++++++++++++ Test/test_report.md | 103 ++- docs/modification-assessment-v1.5.md | 880 +++++++++++++++++++++++++ docs/tasks.md | 5 +- 13 files changed, 2251 insertions(+), 10 deletions(-) create mode 100644 Releases/pinmap-to-pinlist-v1.3.14.zip create mode 100644 Releases/pinmap-to-pinlist-v1.3.15.zip create mode 100644 Test/fixtures/BallList-Template.xlsx create mode 100644 Test/fixtures/BallMAP-Template.xlsx create mode 100644 Test/fixtures/template_corrupt.xlsx create mode 100644 Test/fixtures/template_minimal.xlsx create mode 100644 Test/fixtures/template_narrow.xlsx create mode 100644 Test/test_plan_v1.5.md create mode 100644 docs/modification-assessment-v1.5.md diff --git a/Code/src/test_pinmap.py b/Code/src/test_pinmap.py index b45faeb..dc7f480 100644 --- a/Code/src/test_pinmap.py +++ b/Code/src/test_pinmap.py @@ -363,6 +363,227 @@ def test_f012_pinname_position(): print(f"✓ test_f012_pinname_position passed (5×5={len(pm.pins)} pins)") +# ── v1.5: Template path generation tests ────────────────────────── + +def test_template_path_generation(): + """验证两个模板查找函数返回正确的路径格式。""" + from main import _find_balllist_template_path, _find_ballmap_template_path + + result1 = _find_balllist_template_path() + result2 = _find_ballmap_template_path() + + # 返回值要么是 str 要么是 None + assert result1 is None or isinstance(result1, str) + assert result2 is None or isinstance(result2, str) + # 两者应该是不同路径 + if result1 and result2: + assert "BallList" in result1 + assert "BallMAP" in result2 + assert result1 != result2 + + print("✓ test_template_path_generation passed") + + +def test_f011_default_styles_xml(): + """F011: 无模板时 _styles_xml() 返回硬编码默认样式。""" + from xlsx_writer import StyledXLSXWriter + + writer = StyledXLSXWriter(style=None) + xml = writer._styles_xml() + + # 验证硬编码默认值的存在 + assert 'Calibri' in xml, "默认字体应为 Calibri" + assert 'thin' in xml, "默认边框应为 thin" + assert 'center' in xml, "默认对齐应为 center" + assert 'cellXfs count="4"' in xml, "应有 4 个 xf" + + print("✓ test_f011_default_styles_xml passed") + + +def test_f011_template_fonts_in_styles_xml(): + """F011: 有模板时 _styles_xml() 使用模板的字体信息。""" + from template_reader import TemplateStyle, FontStyle + from xlsx_writer import StyledXLSXWriter + + # 构建一个模板样式:微软雅黑 12pt + style = TemplateStyle() + style.fonts = [ + FontStyle(name="微软雅黑", size=12.0, bold=False, italic=False, color="FF000000"), + FontStyle(name="微软雅黑", size=12.0, bold=True, italic=False, color="FF000000"), + ] + style.fills = [] + style.borders = [] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '0', 'xfId': '0'}, + ] + + writer = StyledXLSXWriter(style=style) + xml = writer._styles_xml() + + assert '微软雅黑' in xml, f"模板字体名应出现在 styles.xml 中\n{xml[:500]}" + assert '12' in xml or '12.0' in xml, f"模板字号 12pt 应出现在 styles.xml 中" + + print("✓ test_f011_template_fonts_in_styles_xml passed") + + +def test_f011_output_dims_determined_by_pins(): + """F011: 输出文件的 dim 由实际 Pin 数量决定,不复制模板的行列结构。""" + from template_reader import TemplateStyle, FontStyle + from xlsx_writer import StyledXLSXWriter + + style = TemplateStyle() + style.fonts = [FontStyle(name="Calibri", size=11.0)] + style.column_widths = {i: 20.0 for i in range(100)} # 模板有 100 列 + style.row_heights = {i: 30.0 for i in range(200)} # 模板有 200 行 + style.fills = [] + style.borders = [] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '0', 'xfId': '0'}, + ] + + # 仅输出 2 行 2 列的数据(模拟 2×2 PinMAP + A1) + data = { + 'A1': 'QFP-8', + 'A2': '1', 'B2': 'Pin1', + 'A3': '2', 'B3': 'Pin2', + } + + writer = StyledXLSXWriter(style=style) + sheet_xml = writer._sheet_xml(data) + + # dim 应该反映实际数据范围(A1:B3),而非模板的 100 列 + assert 'dimension ref="A1:B3"' in sheet_xml, \ + f"dim 应由实际数据决定,不应包含模板的 100 列\n{sheet_xml[:500]}" + + # 不应出现 row r="201"(模板的第 200 行) + assert 'row r="201"' not in sheet_xml, "不应包含模板的多余行" + + print("✓ test_f011_output_dims_determined_by_pins passed") + + +def test_f011_template_borders_in_styles_xml(): + """F011: 有模板时 _styles_xml() 使用模板的边框样式(而非硬编码 thin)。""" + from template_reader import TemplateStyle, BorderStyle, FontStyle + from xlsx_writer import StyledXLSXWriter + + style = TemplateStyle() + style.fonts = [FontStyle(name="Calibri", size=11.0)] + style.borders = [ + BorderStyle(top="none", bottom="none", left="none", right="none"), + BorderStyle(top="medium", bottom="medium", left="medium", right="medium"), + ] + style.fills = [] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '1', 'xfId': '0', + 'applyBorder': '1'}, + ] + + writer = StyledXLSXWriter(style=style) + xml = writer._styles_xml() + + # 模板的 medium 边框应该存在(不仅仅是 thin) + assert 'medium' in xml, f"模板 medium 边框应出现在 styles.xml 中\n{xml[:800]}" + + print("✓ test_f011_template_borders_in_styles_xml passed") + + +def test_f011_template_fills_in_styles_xml(): + """F011: 有模板时 _styles_xml() 使用模板的填充色。""" + from template_reader import TemplateStyle, FillStyle, FontStyle + from xlsx_writer import StyledXLSXWriter + + style = TemplateStyle() + style.fonts = [FontStyle(name="Calibri", size=11.0)] + style.borders = [] + style.fills = [ + FillStyle(pattern_type="none", fg_color=""), + FillStyle(pattern_type="solid", fg_color="FFFF00"), # 黄色 + ] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '0', 'xfId': '0'}, + {'numFmtId': '0', 'fontId': '0', 'fillId': '1', 'borderId': '0', 'xfId': '0', + 'applyFill': '1'}, + ] + + writer = StyledXLSXWriter(style=style) + xml = writer._styles_xml() + + assert 'FFFF00' in xml, f"模板黄色填充应出现在 styles.xml 中\n{xml[:800]}" + + print("✓ test_f011_template_fills_in_styles_xml passed") + + +def test_template_empty_fonts_fallback(): + """边界测试:空 fonts 回退到默认字体。""" + from template_reader import TemplateStyle + from xlsx_writer import StyledXLSXWriter + + style = TemplateStyle() + style.fonts = [] # 空 fonts + style.fills = [] + style.borders = [] + style.cell_xfs = [] + + writer = StyledXLSXWriter(style=style) + xml = writer._styles_xml() + + # 应回退到默认样式:Calibri 11pt + assert 'Calibri' in xml, "空 fonts 应回退到默认 Calibri" + assert 'thin' in xml, "空 borders 应回退到默认 thin" + assert 'cellXfs count="4"' in xml, "应有 4 个 xf" + + print("✓ test_template_empty_fonts_fallback passed") + + +def test_template_color_prefix_auto_fix(): + """边界测试:FF 前缀补全。""" + from template_reader import TemplateStyle, FontStyle, FillStyle + from xlsx_writer import StyledXLSXWriter + + style = TemplateStyle() + # color 缺少 FF 前缀 + style.fonts = [FontStyle(name="Calibri", size=11.0, color="000000")] + style.fills = [ + FillStyle(pattern_type="none"), + FillStyle(pattern_type="solid", fg_color="FFFF00"), # 已有 FF + ] + style.borders = [] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '0', 'xfId': '0'}, + ] + + writer = StyledXLSXWriter(style=style) + xml = writer._styles_xml() + + # 即使原始 color 是 "000000",输出也应是 "FF000000" + assert 'FF000000' in xml, f"color 应自动补全 FF 前缀\n{xml[:800]}" + + print("✓ test_template_color_prefix_auto_fix passed") + + +def test_template_no_styles_xml(): + """边界测试:缺失 styles.xml 时优雅降级。""" + from template_reader import read_template_styles + import tempfile, os + import zipfile + + tmpdir = tempfile.mkdtemp() + try: + bad_path = os.path.join(tmpdir, "no_styles.xlsx") + with zipfile.ZipFile(bad_path, 'w', zipfile.ZIP_DEFLATED) as zf: + zf.writestr('[Content_Types].xml', '') + zf.writestr('xl/worksheets/sheet1.xml', '') + + style = read_template_styles(bad_path) + assert style is not None, "缺失 styles.xml 不应导致 read_template_styles 返回 None" + assert len(style.fonts) == 0, "无 styles.xml,font 列表应为空" + assert len(style.fills) == 0, "无 styles.xml,fill 列表应为空" + print("✓ test_template_no_styles_xml passed") + finally: + import shutil + shutil.rmtree(tmpdir, ignore_errors=True) + + if __name__ == "__main__": test_4x4_parse() test_4x4_validate() @@ -373,4 +594,14 @@ if __name__ == "__main__": test_no_pins() test_12pin_square() test_f012_pinname_position() + # v1.5 新增测试 + test_template_path_generation() + test_f011_default_styles_xml() + test_f011_template_fonts_in_styles_xml() + test_f011_output_dims_determined_by_pins() + test_f011_template_borders_in_styles_xml() + test_f011_template_fills_in_styles_xml() + test_template_empty_fonts_fallback() + test_template_color_prefix_auto_fix() + test_template_no_styles_xml() print("\n✅ All tests passed!") diff --git a/Releases/pinmap-to-pinlist-v1.3.14.zip b/Releases/pinmap-to-pinlist-v1.3.14.zip new file mode 100644 index 0000000000000000000000000000000000000000..f9b5bd451641746fc7c0b3defe14be67496c4e9e GIT binary patch literal 79108 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�dvc8N9qjh~b47YQR+mCeboCP3At^?Unu$1u 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 L7|;fpTz{hNo2!5>btu2$D&2q-fA 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 bhn?YXWGK+P763p2`YjE5Ey|^Rcp3VC^qZH2 literal 0 HcmV?d00001 diff --git a/Releases/pinmap-to-pinlist-v1.3.15.zip b/Releases/pinmap-to-pinlist-v1.3.15.zip new file mode 100644 index 0000000000000000000000000000000000000000..14774a71dcd73c945f095e4f7dabf41f3036d9f7 GIT binary patch literal 157238 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

nhSs(WpT}zAS5w?L- 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 Hmw^2r5Hh7x literal 0 HcmV?d00001 diff --git a/Test/fixtures/BallList-Template.xlsx b/Test/fixtures/BallList-Template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e4d0fa47a669a50385cbfbd97e73ca6bb84f461e GIT binary patch literal 2542 zcmZ`*2Q=Gz8&1R)qX=4R*4~7m1XXD@)E=qYjTkXXs$x~OxIUw?I^5c`MQgjUs)+fK zXzQY?Evf^p*650I|LUCUYrcDvbMia+|IhQD^E}V{yzkEj4Ph1pfk5n_Mr{9CR7XgMdH+z*ASVkYEBfnBd_+48?}KsYM3iYwgk2OqzUM>&kiV9IBBT{VP2W2W+kS zBs5wY@n#9*uoNx$@6Ji zk=(kGHN@mT;dR^Q6={BDZ)=^9@Qg{jtblQF3g5VJ8OM;R8nr3wz>`Bx3hEV)(RUK4 zZ`Y4}5syK7*R)Ysb#)ut-Aq5b@t>Jr@uj|B2;k8?Qz|KZHn?*e2LHx>z+6AHN++{F zv3s$YByM>7lWMGr@+p)|bV80qH>~6t=9|!??>bkT^**ehn54l`#XJEE|2b}B$)0zn zZ>2`0BGhy1YZ)h`@Rf!y?!(&R&LvoYRB_zc9WmbgSXtu^>#D4yskl{*n{i3bVP7HZ z7j1sg(k*#ItqIUj1<;cVI6cC!_;7W#-QRTT1D*s8KGu)|yla3f7r z2MTSXtXyHwpJ#ZBiK$or+V9ij?h2-%lp#uvnP^l?_H}2ee=)x>>0mNZ4CP}ZY!1a#Yw9E_K^yPMI$ne#A z?vW*@`05!km&P+&$(8p+VFeaOzVNw$8~0Nc(33uVb$;8@h}o11cuBX|(7^2CS;O)tn! zRVW^@sXh{k6}S4Ft*cQ6cm6W~;Yny)IH;&>geEB3lQH=$`IBHx%Fu_@`CgPTyE{j2 zNA|;52?N9P7q6Xs2b0z#=gchg`6fpASpJA9;X0clB^*wtvfLn!hp8iZS!EmtP1L%W z>4cdH_n8Y=I_Oun(t_2R6n_@2lK0MRCp9~&{J%a>*1Wr{<_}Sbq=((> zb8|~Vf?TZ0_Rw>lQb}&D{u2Jj6t!0d`tF)AiGGxRcRH}8!1tAs9B29C0mIT9IIlsm z(Y#5N>mk9z$ zZJ9wJ?mbDu2}C?L{O62tKm#i9&3+L)Mn_pFlnc&WR)e}B5`$r`Ei8`)PiB)|9WpYb z(i}tVqcSq^l^jy#67%UO>%2-t$PxL*W*vNa42{PQc`#ky-sTTGv;4IIVjQs-W5Q7m z=W!TDD1F34WHLV!*`z5XrinBFftVj zpPK9JAo6X)U{>-S>JzQvomRk3fnjo*4nO!bNa}|%f`}FEfAw- z-AD6ZB2Vo=8?1lr?KKtu>s5e(oPe3TivUP+xSv-T_MAN-%s&|S)6bw0O&%c5EVRzb z-#Q)(I`AE{n7V1206AXkFQaq%jvI5Uyrl-AzUxKn=qDK4W?zb#G}m$iQ{s~{T^rn7 zgi-D1A{WEvxRY0fo)3l+61{|SJyKLRq!&yBgQL<4M&QzmuL~;P%HFrHB;KaAK9e~m zwo!36!r;3}Q64y40f3bUkXn&FX1jR}_rqcd;Q&eC(A@3TM7!C5UP-~ORr^7*N4l?Qc~v=f zg+n(&H6`er?UlB&XuAK?3qb-?>1)I;W1fc5@un(gq#sV7gax0R9-eqAuGjIP6IlaF zR0vXa#lez8V4gBU_|R=__$l)oDE=j_Z>m<4$FVdGik?*bT`u}fdK$-f2v5FqgSdGG zrAeWnKJ#gUi)3FwP|m0<$vK+Gwc&Yg{DAG^Q^~cIw6VkBgG8}a)5-cdlftm~OUlP_ z$kWzG{CAFQs1yrxU`Ej&MOp^yea3|kV%0M1E<)CBMf8we`e&ZVgt7Zu>6_HK3qrq4 zFRAod5SL9?jo#+69W)wDA5cG!kbSh%Gfb}wo3|ZHwo19S?gjNwO`RKg!DnoP1~Uml z{{3D6sQL2~56JtEw*Ki_0p5Z@ OY{0h%kXVR)_upT~_4m2} literal 0 HcmV?d00001 diff --git a/Test/fixtures/BallMAP-Template.xlsx b/Test/fixtures/BallMAP-Template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0b87a2c34c3743afda0f927f89486a0567f73d29 GIT binary patch literal 2538 zcmZ`*2{csw8y<$i*q1@ps7OO*>`8-ceGM6seP_nlWyux^k^0CIqGStMzls#18Ecws z5o+ur3R5P+DE}+x{QH{Ickem(ckaFCdCz&?=Y8Jy#h}4V0w55G6;zAuv`3A|8i+E0 zKzd*hh#&ZBr|0h%jP(n4vIq~r200uJ^Yy7di#BCM^0ZLlxsGfKVTjJ9R$`Z#NxLMX zzSc+2X;Hv^r+K`?>hJw5XENp^aZ1&K$35N(^5;x>qxjGE_E#1pJH6S)hHE#>{H+wm zsTNihp4cu#HG8}y%?EciRrL=_88J`y8emA`84$Y1)~$QAuP&W;NW}86V(B2dJhpFv zdhnaXMU-n*V+TY{t+vTQcin-{c4i6Jw>;~`g|sc+FJ$l6`~#-4$;xYREa1LsTIUtQ zTw$t&)}1d3QS$K9h6f^JZ%PtiMPoLbg0Ht!;~#6RP>n|VRSXNcyk@WIV~kmIZQGZs zgi8aQw>R!V!TIkIIFFUpxt&WeFR8-l-f}VSyr@Ik&rI*9AHVKFLEMT?unOD&Q$sPo z<(M$Ohw?x^*@4q35bG19cy#xf-1nR-7QqAgoL7eT%Z`mhCbYU5TXUjx6uR;; z5hix9iHQ_fF)_u^Ny;khjgt4e{s$u^##I$?f}z>*Tt`B6!%_<2Vrpq-E(g?lK<}JP z2kbEiayD@wLXdZsnL}!n|AQl^20B08fL~p_!6reY@vdFD%-aK#9&axM*Ly0;7P&Rzv$Fy~aw^~-*o7cb>KVL{}Ig{vc7z&rN? zeAL$zNnuzCll2TW#61BMiun?v?8^ZH7Xuj%=CF zGKf)WZ=70$NozFRB!A+;UAf?9{QY7PyM2dsH|L+qR;TrNwIMiSC{fU2+RVK;q~RUM z&VrHZNRSKsJl<6lP3tE23Dm1Tcqkshm)>8-T|VC2ml09&%8dh(TLCd38mcD{3DoK7 zkAed1ki@eb?#@yP4o^HKJx|IhFLkw7=rD?YmR>yLU4Iw%{)h~;WUx!C_@)ZCX5on$ zod~-Tbw+bhNyfU-qeYXhs7JEtj2&93!W%~( zqOO!4vFLxk<)gURCZXIQ+dVh6yXF4d#OwvY1Q|Q=SKBU_5doz7X;OK3`Izapy zCJ=~oFC{_2;Xc@)UHKnd5L1Q_9L-di*@_R&5+08sXX;e6=NQc7dJd|YyILiAsMbCw zr0q;`Z-{PiFV(jR_7I><4Wr>n`T5Ir9m`UX5Q_OaYsrM8Z(U%&^QS_^HCofwCc0Y5 z2JfpAP=ac#@~`wTD0K^(9d70+pZQsjw8TjeBhZ3SZRLWNvi7RYPMq z<|AsuU5eHUa%%Jnszk=XnOnA2{217#?l_sy=x2Sa9Qt6O=f#sg$>-6V2d(26GERT5 z84796$s*uzPhZv2;5FUuW}oynY!txfkhap<1@p4CzTu%_NQUV9_4{EOOG4~dl^PsOL@4U;8^knVtM)gYZ~va1g)|IFP#~ zoS8;G0~k4h@=YL(k`oDvFFiOY6CVZ&i@Cq{?wU+_dOwjon-!-P!uPIZc`_d*8%T4B zM4DgC3x%$RKw|CZKJ}_X9i8s_N$9k@+xtdPP7!4dMn7h1ZG9HBD>^7VRTQgM;u0rZ znN^kKt(`jCO=R)r%Pu5pFe$A)bB~mNv?NizD7KKv^JqoB;jfcSnukZ{Zbz|c+?Y=` z%6MgQUVPh(=>qeB40Ff$d;8|D_shy5Jwv4F<1eSZuB~X0mS2>8X2c)+XgqWOkfpY< z`@*r7r;JW_rl|Y!^QSMx(XbCT`ih^m7TZseND`!}Wh{4+>_3WMC?jh^7&HT;0QkRm z0w8HWuNa^-{dvFjahQSyJ@vpH+52PP5zkqUpdUPX)9!%e}e}RR7G#Vgc?} LAjN#FyKnyk`7|2r literal 0 HcmV?d00001 diff --git a/Test/fixtures/template_corrupt.xlsx b/Test/fixtures/template_corrupt.xlsx new file mode 100644 index 0000000..18245c2 --- /dev/null +++ b/Test/fixtures/template_corrupt.xlsx @@ -0,0 +1 @@ +This is not a valid xlsx file. It's just plain text pretending to be xlsx. \ No newline at end of file diff --git a/Test/fixtures/template_minimal.xlsx b/Test/fixtures/template_minimal.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8f06dfb25ddf6fc0f655dcf1fc90ad0a8b7b971f GIT binary patch literal 2331 zcmZ`*2UHX38VxP9Py_-jz4&OM1OfyQ14vN`9hKe*y(cUQZGojMy+4(uiwG)6_XP7}xSeZM!3LZ|`>?aS~ zS`JFWyV^sHJvIbUhoI+dAs7%> zay0N<+W5zWj6tDY+s;iHKA5+)Rya0q)~+aMiXoGCN~n%~#7K3bqv*m*ky{FC^)Jwk zDHFf$UObS9M|nT)9s+A?w?A_;`sl{zyt3&xv9%h+t?qnJO2{>g^a-l@2ipZx-G~OQ zLP}cST1|n3e);bz3Cb{YGugP563ISj?JK801pj-amD;KEe)sC^q^4O7chG8@)q3BY!|2F(iV!A`r zA=7S*%~x8wW$dYT02(R-dU67*M-(OmtEPH-&YgJ9odV|tf2ep65OzD|d-e2wZwp5* zl%dLSl})Ur3v_WY&s$7PE#~$14s=>0_@l}CRSm`+O{R1++e>BceNDv8yuSE?`qDB8 zhvSs-O}QaxCq#WUV=7kg!YT_ydX9hHol6H@RbvUJTG|J7(zV@F_erC<| zb80Ks=(}4f1M86c$qkmCVXe27|1cvP@=czE!sNph`6^ZMbCo?U3+cEP^~IBtd#r7n&? zqcPM(2EL>;Z?@z=muJ}@A3=zW;p= zn>%}HPcb<`QcpiJCjZ(7R7QtbLj8@`FYQ|&i<9_TPS;FnAuMfz8ORIP+U(w_Pp2h{zL~-o>Uwk0ovWH+(vKca+ z+_$^D{7z7S6P#fW@%5BWcY7Kr8F)nzu{k{W(2!B|gUp6ia95?@8zni8`!9y|@0Dos z=+#_aF^qMYMe0={s;LT{{SQfqf`ev;Xh*&iR!Lf72TpQp)WRrnuJ*Mzs!hI#aY(;F z_)w`8l~%8GWAgb?h}y=01cE3(vbJ=*)uHrx8Jl1$=_IEoq`OuHZgM{%(Myse)Ru_= zHh&+GgzHQaERGO@!G6gIJF?ZF6fcPeO?`&eq6okEmfx}r|9h>RyOUn%bBRWhsnrG$&kGDFzdsdZAGCMW7YnJ$#dsWnS zc;%VY#0`Dxl4_RRa!yFRM$w*_x&KHM+@TO)vf>G_E89jh(r#^LuKx2)Eq1c@bTRCzF;Z~bmtv&-0Ev32E(dPb*gX$N@v|KOF49qDfAI^r# z(H1Ru5S@GGIb+`lz+yH@n%$8 zW@57=B3|(vIlKlrW-dOIy!KLLf96J5P}Y&;*IhGikxcFbUY;AUiSQYT(|*AQU@$l= zzz0~=Pu*gfZxl3O2r)g-O`Gg3tT0vd^1C9n$GpJ+cFDB7EP@az-}_j)VAmaAw75Q6 zQ5l$$mYwIM-$er_-yc0uh{>0nJ-CfzZn8bn!Fc6+JjQceI{0bLp7kw>lu?%qc?fZB;p$(UR9LC1!KfOi`La4S< zN^{VOhONzq1KJz6y5brnrjKIvJtNQoVk%_Y16a{r7nzf6+}?rtA=n1Zz$n1<&qEZT z{^geh=KpE>!@oS=u&+x{H-1Iynx0euB}&z)DW1pleP|2fbG%>q0Hfmnf~ACTCX H_4Mk0Bv+Hl literal 0 HcmV?d00001 diff --git a/Test/fixtures/template_narrow.xlsx b/Test/fixtures/template_narrow.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d25407400d6c1133b454640c74214ad076bd4009 GIT binary patch literal 2381 zcmZ`*2{=@H8=o;5>mX*3u{09dXRL_^pDcZ2%}z5kj6K_sv5bo>3B}N@Tzj&WBIMe) zhO1;rxISB!Qm!rY6`_1bp67PWckemRIq!4M|M|Vo`ThRy`+JWi4srwz0)f~;HKgu~ z*fAMHBp3uTfPg>(z*}d70RIq@e~61scp!<4SE5|@tF*>huweLF8S>c#4n+#Od%3ft z$I9%P1o~->pMlE1 zt~_qwJws|!JPJ#E*hq(JXw)>}^*`hJo#vK323F>McrZ@)jtgD%Z~2B$`@(+IP%E%Z zJ)=9J{cT~oxK7STMXG}Qzl}~r#$`#gBZ?*+zX-nCR*$bcy~;2i8&oqYr>cPY54WVRV1FC~q$Hq;9iC8BIIIa}9kbI?+CO z3&IGqJftN)>Ay;~fQAZyo?Jk52`2fGm6i7IX#;IMacDm1dTyzg|LwS|n8Z$^sRInF zr`VHk8DZv(n4Z2t6ctqtn_1gHjHvj2KDTJB!m^Xqc#g+5SwNo0 zSHoT`*~L7V5Ot_=+D$5bghb?>KkK13+jIMI$|>BK8()>zH%ZN@23b@!v?s+(;xte^UORYhJ>O0eJPy}Jcou092m2-oy8pJV-DQ9tF@v!Sy^!!M_p0NE* zPpS3DPRPUvVIq{Y13JuB5^gy+0kG6%0f9sg*dFZWUpar@*~*NUK3!<;m^CWry`8z@ zs~DpkLU+MfWhCg5e2^CriQDO&7=S-juc{V{;HM3i@|I7v3}i;!?{njZW>-KBJB&0F zJK7nuvrB?-E@+Z9x4SDU5nt~u;r%aJ)#aXN6?!blb;%FrzEAT!7UZNk?+^Fr+{;qq zJyUpgPA|fFO!G{>YQe;*y3UFg)%49r;7|wtuWS-K(X}BGD=$p-qkk`&A!47%&{*g? z>B3ub)!2j*Ih(<@Z9nA?UE-<@GQDr#?5@b>5?hzL{%%2^HH}4?gn{evg!oybt%(5wV0*@7_wNmR|F;lfW zpRoT~t@v2-BB6)74+(v~@?Jq(?^?GTJwSuiGv;|cwCQ?VoB9}U4qdAH*60bFsJP$i zKiM7|cAu?dGf9P`?V2sTDR9XO@tjnoE{OjgHBeOs|Nd3h@SjJQ<9Z7=M%e@#@$_Fx?ieT1B{3G5dh}?X zGh9dY7|LVO0LQWW#xB)?bu{|DYNYXU*|Amp{43lq^)-`oHnew6O8kEiU*k~ULbH1> zRSgfDDrzNLx#(4YES;1clww(!0)p_n@#1;sAjq@`{rUQ5v`z>jyVA-@e}ILxFG zETgES+X9D6E!Ii?S|*_96X4qSWuURhUYCMN?$#l}-u|B7vU2jk5PRfStxLKzGfLUikju6KeaBKfXZ-ULr9rO$d{e3nef@nG>t6U7vVOeU`yRvW@uN(9r4PuLtj&K{w;1FDwoP8~74qJb< zv@49r?GxEx?^}v&5E?E;wTbs$2}|jn*sRMMhk4r5>h!2e*9 z%z2o--M}n}<0AbFKc!U=00Jf&Z&qOB^e(3IeeKXD1+W JDBJ$i{{V^svWNfx literal 0 HcmV?d00001 diff --git a/Test/run_tests.py b/Test/run_tests.py index e6ed6e4..aa287dd 100644 --- a/Test/run_tests.py +++ b/Test/run_tests.py @@ -561,6 +561,342 @@ def test_list_to_map(r: TestRunner): shutil.rmtree(tmpdir, ignore_errors=True) +# ── Part 3: v1.5 Template / Style Integration Tests ──────────────── + +def test_v15_styles(r: TestRunner): + """v1.5: 模板分离与样式应用集成测试(方案B — 直接调用底层函数传入 fixture 路径)。""" + fixture_dir = os.path.join(os.path.dirname(__file__), 'fixtures') + tmpdir = tempfile.mkdtemp(prefix="pinmap_v15_") + from xlsx_writer import write_xlsx_with_style + + try: + # ── TC-v1.5-001: MAP→List 加载 BallList 模板 ── + def _tc_v15_001(result): + template_path = os.path.join(fixture_dir, 'BallList-Template.xlsx') + assert os.path.exists(template_path), f"BallList 模板文件不存在: {template_path}" + + style = read_template_styles(template_path) + assert style is not None, "BallList 模板样式应成功读取" + assert len(style.fonts) > 0, "应有字体定义" + assert len(style.borders) > 0, "应有边框定义" + assert 0 in style.column_widths, "应有列宽定义" + result.ok(f"模板加载成功: fonts={len(style.fonts)}, borders={len(style.borders)}, width_A={style.column_widths.get(0)}") + + r.run("TC-v1.5-001: MAP->List 加载 BallList 模板", _tc_v15_001) + + # ── TC-v1.5-002: MAP→List 无模板降级 ── + def _tc_v15_002(result): + style = read_template_styles('/nonexistent/nonexistent_template.xlsx') + assert style is None, "不存在的模板应返回 None" + result.ok("无模板文件时优雅返回 None") + + r.run("TC-v1.5-002: MAP->List 无模板降级", _tc_v15_002) + + # ── TC-v1.5-003: List→MAP 加载 BallMAP 模板 ── + def _tc_v15_003(result): + template_path = os.path.join(fixture_dir, 'BallMAP-Template.xlsx') + assert os.path.exists(template_path), f"BallMAP 模板文件不存在: {template_path}" + + style = read_template_styles(template_path) + assert style is not None, "BallMAP 模板样式应成功读取" + assert len(style.fonts) > 0, "应有字体定义" + assert len(style.borders) > 0, "应有边框定义" + assert 0 in style.row_heights, "应有行高定义" + result.ok(f"模板加载成功: fonts={len(style.fonts)}, borders={len(style.borders)}, row_height={style.row_heights.get(0)}") + + r.run("TC-v1.5-003: List->MAP 加载 BallMAP 模板", _tc_v15_003) + + # ── TC-v1.5-004: List→MAP 无模板降级 ── + def _tc_v15_004(result): + style = read_template_styles('/nonexistent/nonexistent_template.xlsx') + assert style is None, "不存在的模板应返回 None" + result.ok("无模板文件时优雅返回 None") + + r.run("TC-v1.5-004: List->MAP 无模板降级", _tc_v15_004) + + # ── TC-v1.5-005: 两个方向独立使用各自模板 ── + def _tc_v15_005(result): + bl_path = os.path.join(fixture_dir, 'BallList-Template.xlsx') + bm_path = os.path.join(fixture_dir, 'BallMAP-Template.xlsx') + + style_bl = read_template_styles(bl_path) + style_bm = read_template_styles(bm_path) + + assert style_bl is not None, "BallList 模板应成功加载" + assert style_bm is not None, "BallMAP 模板应成功加载" + + # BallList 有列宽,BallMAP 有行高 + assert 0 in style_bl.column_widths, "BallList 应有列宽" + assert 0 in style_bm.row_heights, "BallMAP 应有行高" + result.ok(f"两个模板独立: BL fonts={len(style_bl.fonts)}, BM fonts={len(style_bm.fonts)}") + + r.run("TC-v1.5-005: 两个方向独立使用各自模板", _tc_v15_005) + + # ── TC-v1.5-006: 模板损坏优雅降级 ── + def _tc_v15_006(result): + corrupt_path = os.path.join(fixture_dir, 'template_corrupt.xlsx') + assert os.path.exists(corrupt_path), f"损坏模板文件不存在: {corrupt_path}" + + style = read_template_styles(corrupt_path) + assert style is None, "损坏模板应返回 None(优雅降级)" + result.ok("损坏模板优雅返回 None") + + r.run("TC-v1.5-006: 模板损坏优雅降级", _tc_v15_006) + + # ── TC-v1.5-007: 模板字体应用到输出文件 ── + def _tc_v15_007(result): + template_path = os.path.join(fixture_dir, 'BallMAP-Template.xlsx') + style = read_template_styles(template_path) + + assert style is not None, "模板样式应成功读取" + + # 用模板生成 3x3 PinMAP + entries = [PinListEntry(number=i+1, name=f"PIN{i+1:02d}") for i in range(12)] + outpath = os.path.join(tmpdir, 'v15_007_output.xlsx') + generate_pinmap(entries, 3, 3, "QFP-12", template_style=style, output_path=outpath) + + # 验证输出 styles.xml 包含模板字体 + import zipfile + with zipfile.ZipFile(outpath, 'r') as zf: + assert 'xl/styles.xml' in zf.namelist(), "输出应包含 styles.xml" + styles_xml = zf.read('xl/styles.xml').decode('utf-8') + assert '宋体' in styles_xml, f"输出 styles.xml 应包含宋体" + assert '14' in styles_xml, f"输出 styles.xml 应包含字号 14" + + result.ok("输出 styles.xml 包含模板字体(宋体 14pt)") + + r.run("TC-v1.5-007: 模板字体应用到输出文件", _tc_v15_007) + + # ── TC-v1.5-008: 模板列宽应用到输出文件 ── + def _tc_v15_008(result): + template_path = os.path.join(fixture_dir, 'BallList-Template.xlsx') + style = read_template_styles(template_path) + assert style is not None, "模板样式应成功读取" + + # 用模板生成 MAP->List 输出 + data = {'A1': 'QFP-44', 'A2': 'Pin1', 'B2': '1', 'A3': 'Pin2', 'B3': '2'} + outpath = os.path.join(tmpdir, 'v15_008_output.xlsx') + write_xlsx_with_style(data, outpath, style) + + # 验证列宽 + import zipfile + import xml.etree.ElementTree as ET + _S = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main' + with zipfile.ZipFile(outpath, 'r') as zf: + sheet_xml = zf.read('xl/worksheets/sheet1.xml') + root = ET.fromstring(sheet_xml) + cols_elem = root.find(f'{{{_S}}}cols') + assert cols_elem is not None, "输出 sheet1.xml 应包含 cols" + cols = cols_elem.findall(f'{{{_S}}}col') + assert len(cols) >= 2, f"应有至少2列宽度定义,实际: {len(cols)}" + width_a = float(cols[0].get('width', '0')) + width_b = float(cols[1].get('width', '0')) + assert abs(width_a - 25.0) < 0.5, f"A列宽 ({width_a}) 应与模板 25 接近" + assert abs(width_b - 18.0) < 0.5, f"B列宽 ({width_b}) 应与模板 18 接近" + + result.ok(f"列宽验证通过: A={width_a:.1f}, B={width_b:.1f}") + + r.run("TC-v1.5-008: 模板列宽应用到输出文件", _tc_v15_008) + + # ── TC-v1.5-009: 模板行高应用到输出文件 ── + def _tc_v15_009(result): + template_path = os.path.join(fixture_dir, 'BallMAP-Template.xlsx') + style = read_template_styles(template_path) + assert style is not None, "模板样式应成功读取" + + entries = [PinListEntry(number=i+1, name=f"PIN{i+1:02d}") for i in range(12)] + outpath = os.path.join(tmpdir, 'v15_009_output.xlsx') + generate_pinmap(entries, 3, 3, "QFP-12", template_style=style, output_path=outpath) + + import zipfile + import xml.etree.ElementTree as ET + _S = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main' + with zipfile.ZipFile(outpath, 'r') as zf: + sheet_xml = zf.read('xl/worksheets/sheet1.xml') + root = ET.fromstring(sheet_xml) + sheet_data = root.find(f'{{{_S}}}sheetData') + rows = sheet_data.findall(f'{{{_S}}}row') + found_ht = False + for row in rows: + ht = row.get('ht') + if ht: + found_ht = True + ht_val = float(ht) + assert abs(ht_val - 25.0) < 0.5, f"行高 ({ht_val}) 应与模板 25 接近" + break + assert found_ht, "至少应有一个 row 包含 ht 属性" + + result.ok("行高验证通过: ht=25") + + r.run("TC-v1.5-009: 模板行高应用到输出文件", _tc_v15_009) + + # ── TC-v1.5-010: 两个方向使用不同模板各自的格式 ── + def _tc_v15_010(result): + bl_path = os.path.join(fixture_dir, 'BallList-Template.xlsx') + bm_path = os.path.join(fixture_dir, 'BallMAP-Template.xlsx') + + style_bl = read_template_styles(bl_path) + style_bm = read_template_styles(bm_path) + assert style_bl and style_bm, "两个模板都应该成功加载" + + # MAP->List 方向:用 BallList 模板 + pinlist_data = {'A1': 'QFP-44', 'A2': 'Pin1', 'B2': '1'} + pinlist_path = os.path.join(tmpdir, 'v15_010_pinlist.xlsx') + write_xlsx_with_style(pinlist_data, pinlist_path, style_bl) + + # List->MAP 方向:用 BallMAP 模板 + entries = [PinListEntry(number=i+1, name=f"PIN{i+1:02d}") for i in range(12)] + pinmap_path = os.path.join(tmpdir, 'v15_010_pinmap.xlsx') + generate_pinmap(entries, 3, 3, "QFP-12", template_style=style_bm, output_path=pinmap_path) + + import zipfile + with zipfile.ZipFile(pinlist_path, 'r') as zf: + pl_styles = zf.read('xl/styles.xml').decode('utf-8') + with zipfile.ZipFile(pinmap_path, 'r') as zf: + pm_styles = zf.read('xl/styles.xml').decode('utf-8') + + assert '楷体' in pl_styles, "BallList 输出应包含楷体" + assert '宋体' in pm_styles, "BallMAP 输出应包含宋体" + + result.ok("两个方向输出字体不同: BL->楷体, BM->宋体") + + r.run("TC-v1.5-010: 两个方向不同模板各自的格式", _tc_v15_010) + + # ── TC-v1.5-011: 完整往返+模板隔离 ── + def _tc_v15_011(result): + bl_path = os.path.join(fixture_dir, 'BallList-Template.xlsx') + bm_path = os.path.join(fixture_dir, 'BallMAP-Template.xlsx') + + style_bl = read_template_styles(bl_path) + style_bm = read_template_styles(bm_path) + assert style_bl and style_bm, "两个模板都应该成功加载" + + fixture_4x4 = os.path.join(fixture_dir, 'sample_4x4.xlsx') + cells = read_xlsx_cells(fixture_4x4) + pinmap = parse_pinmap(cells) + validation = validate_pinmap(pinmap) + pinlist = generate_pinlist(pinmap, validation) + + pinlist_data = {'A1': pinlist.package_info} + for i, (pin_name, pin_num) in enumerate(pinlist.rows): + pinlist_data[f'A{i+2}'] = pin_name + pinlist_data[f'B{i+2}'] = str(pin_num) + pinlist_path = os.path.join(tmpdir, 'v15_011_pinlist.xlsx') + write_xlsx_with_style(pinlist_data, pinlist_path, style_bl) + + pkg2, entries2 = parse_pinlist(pinlist_path) + pinmap_path = os.path.join(tmpdir, 'v15_011_pinmap.xlsx') + generate_pinmap(entries2, 3, 3, pkg2, template_style=style_bm, output_path=pinmap_path) + + rt_cells = read_xlsx_cells(pinmap_path) + rt_pinmap = parse_pinmap(rt_cells) + assert len(rt_pinmap.pins) == len(pinmap.pins), f"往返后引脚数应一致: {len(rt_pinmap.pins)} vs {len(pinmap.pins)}" + rt_numbers = sorted([p.number for p in rt_pinmap.pins]) + orig_numbers = sorted([p.number for p in pinmap.pins]) + assert rt_numbers == orig_numbers, f"往返引脚序号应一致" + + import zipfile + with zipfile.ZipFile(pinlist_path, 'r') as zf: + pl_xml = zf.read('xl/styles.xml').decode('utf-8') + with zipfile.ZipFile(pinmap_path, 'r') as zf: + pm_xml = zf.read('xl/styles.xml').decode('utf-8') + assert '楷体' in pl_xml, "中间 PinList 应使用 BallList 的楷体" + assert '宋体' in pm_xml, "最终 PinMAP 应使用 BallMAP 的宋体" + + result.ok(f"往返成功: {len(pinmap.pins)} pins, 楷体->PinList, 宋体->PinMAP") + + r.run("TC-v1.5-011: 完整往返+模板隔离", _tc_v15_011) + + # ── TC-v1.5-012: 无模板完整流程 ── + def _tc_v15_012(result): + fixture_4x4 = os.path.join(fixture_dir, 'sample_4x4.xlsx') + cells = read_xlsx_cells(fixture_4x4) + pinmap = parse_pinmap(cells) + validation = validate_pinmap(pinmap) + pinlist = generate_pinlist(pinmap, validation) + + pinlist_data = {'A1': pinlist.package_info} + for i, (pin_name, pin_num) in enumerate(pinlist.rows): + pinlist_data[f'A{i+2}'] = pin_name + pinlist_data[f'B{i+2}'] = str(pin_num) + pinlist_path = os.path.join(tmpdir, 'v15_012_pinlist.xlsx') + write_xlsx_with_style(pinlist_data, pinlist_path, None) + + assert os.path.exists(pinlist_path), "输出文件应存在" + rt_cells = read_xlsx_cells(pinlist_path) + assert (0, 0) in rt_cells, "A1 应有封装信息" + + pkg2, entries2 = parse_pinlist(pinlist_path) + pinmap_path = os.path.join(tmpdir, 'v15_012_pinmap.xlsx') + generate_pinmap(entries2, 3, 3, pkg2, template_style=None, output_path=pinmap_path) + assert os.path.exists(pinmap_path), "PinMAP 输出文件应存在" + + result.ok("无模板完整流程正常") + + r.run("TC-v1.5-012: 无模板完整流程", _tc_v15_012) + + # ── TC-v1.5-013: 极简模板(只有字体) ── + def _tc_v15_013(result): + template_path = os.path.join(fixture_dir, 'template_minimal.xlsx') + assert os.path.exists(template_path), f"极简模板文件不存在: {template_path}" + + style = read_template_styles(template_path) + assert style is not None, "极简模板应成功加载" + assert len(style.fonts) > 0, "应有字体定义" + assert style.fonts[0].name == "Courier New", f"字体应为 Courier New, 实际: {style.fonts[0].name}" + assert len(style.borders) == 0, "极简模板不应有边框" + assert len(style.fills) == 0, "极简模板不应有填充" + + pinlist_data = {'A1': 'QFP-8', 'A2': 'Pin1', 'B2': '1'} + outpath = os.path.join(tmpdir, 'v15_013_output.xlsx') + write_xlsx_with_style(pinlist_data, outpath, style) + + import zipfile + with zipfile.ZipFile(outpath, 'r') as zf: + styles_xml = zf.read('xl/styles.xml').decode('utf-8') + assert 'Courier New' in styles_xml, "输出应包含 Courier New" + + result.ok(f"极简模板: font={style.fonts[0].name}") + + r.run("TC-v1.5-013: 极简模板(只有字体)", _tc_v15_013) + + # ── TC-v1.5-014: 列宽扩展 ── + def _tc_v15_014(result): + template_path = os.path.join(fixture_dir, 'template_narrow.xlsx') + style = read_template_styles(template_path) + assert style is not None, "窄模板应成功加载" + assert 0 in style.column_widths, "应有第 0 列宽" + assert abs(style.column_widths[0] - 15.0) < 0.5 + + entries = [PinListEntry(number=i+1, name=f"PIN{i+1:02d}") for i in range(20)] + outpath = os.path.join(tmpdir, 'v15_014_output.xlsx') + generate_pinmap(entries, 5, 5, "QFN-20", template_style=style, output_path=outpath) + + import zipfile + import xml.etree.ElementTree as ET + _S = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main' + with zipfile.ZipFile(outpath, 'r') as zf: + sheet_xml = zf.read('xl/worksheets/sheet1.xml') + root = ET.fromstring(sheet_xml) + cols_elem = root.find(f'{{{_S}}}cols') + assert cols_elem is not None, "输出应包含 cols" + cols = cols_elem.findall(f'{{{_S}}}col') + assert len(cols) >= 6, f"需要至少 6 列,实际 {len(cols)}" + widths = [float(c.get('width', '0')) for c in cols] + assert abs(widths[0] - 15.0) < 0.5, f"A列应为 15.0, 实际: {widths[0]}" + assert abs(widths[1] - 12.0) < 0.5, f"B列应为 12.0, 实际: {widths[1]}" + assert abs(widths[2] - 10.0) < 0.5, f"C列应为 10.0, 实际: {widths[2]}" + assert abs(widths[3] - 8.0) < 0.5, f"D列应为默认 8.0, 实际: {widths[3]}" + assert abs(widths[4] - 8.0) < 0.5, f"E列应为默认 8.0, 实际: {widths[4]}" + + result.ok(f"列宽扩展正确: A={widths[0]}, B={widths[1]}, C={widths[2]}, D={widths[3]}, E={widths[4]}") + + r.run("TC-v1.5-014: 列宽扩展", _tc_v15_014) + + finally: + shutil.rmtree(tmpdir, ignore_errors=True) + + # ── Main ──────────────────────────────────────────────────────────── def main(): @@ -579,6 +915,10 @@ def main(): test_list_to_map(runner) print() + print("-- Part 3: v1.5 模板/样式集成测试 --") + test_v15_styles(runner) + print() + total, passed, failed = runner.summary() print("=" * 60) print(f" 总计: {total} | 通过: {passed} | 失败: {failed}") @@ -611,13 +951,17 @@ def generate_report(runner: TestRunner, total: int, passed: int, failed: int): # Count by category map_results = [r for r in runner.results if r.name.startswith("TC-MAP")] lm_results = [r for r in runner.results if r.name.startswith("TC-LM")] + v15_results = [r for r in runner.results if r.name.startswith("TC-v1.5")] map_pass = sum(1 for r in map_results if r.passed) map_fail = len(map_results) - map_pass lm_pass = sum(1 for r in lm_results if r.passed) lm_fail = len(lm_results) - lm_pass + v15_pass = sum(1 for r in v15_results if r.passed) + v15_fail = len(v15_results) - v15_pass - lines.append(f"| MAP→List 回归 | {len(map_results)} | {map_pass} | {map_fail} |") - lines.append(f"| List→MAP 新增 | {len(lm_results)} | {lm_pass} | {lm_fail} |") + lines.append(f"| MAP->List 回归 | {len(map_results)} | {map_pass} | {map_fail} |") + lines.append(f"| List->MAP 新增 | {len(lm_results)} | {lm_pass} | {lm_fail} |") + lines.append(f"| v1.5 模板/样式集成 | {len(v15_results)} | {v15_pass} | {v15_fail} |") lines.append(f"| **总计** | **{total}** | **{passed}** | **{failed}** |") lines.append("") lines.append("---") @@ -649,6 +993,19 @@ def generate_report(runner: TestRunner, total: int, passed: int, failed: int): lines.append(f"- **错误**: {r.error}") lines.append("") + # v1.5 details + lines.append("## Part 3: v1.5 模板/样式集成测试") + lines.append("") + for r in v15_results: + status = "✅ 通过" if r.passed else "❌ 失败" + lines.append(f"### {r.name}") + lines.append(f"- **结果**: {status}") + if r.details: + lines.append(f"- **详情**: {r.details}") + if r.error: + lines.append(f"- **错误**: {r.error}") + lines.append("") + # Summary lines.append("---") lines.append("") diff --git a/Test/test_plan_v1.5.md b/Test/test_plan_v1.5.md new file mode 100644 index 0000000..3494d0f --- /dev/null +++ b/Test/test_plan_v1.5.md @@ -0,0 +1,680 @@ +# PinMAP-to-PinList v1.5.0 — 测试方案 + +> **版本**: v1.5.0 +> **日期**: 2026-06-06 +> **设计人**: 测试架构师 (Test Architect) +> **基准**: 修改需求评估 `docs/modification-assessment-v1.5.md` + +--- + +## 1. 变更影响范围 + +| 编号 | 标题 | 影响文件 | 测试重点 | +|------|------|---------|---------| +| F009 | MAP→List 使用 BallList-Template.xlsx | `main.py` | 模板分离后方向独立,互不干扰 | +| F010 | List→MAP 使用 BallMAP-Template.xlsx | `main.py` | 模板分离后方向独立,互不干扰 | +| F011 | 模板格式提取式应用 | `xlsx_writer.py`, `template_reader.py` | 字体/边框/填充/对齐/列宽/行高正确应用 | +| F012 | PinName 位置确认 + 回归测试 | `test_pinmap.py` | 上/下边 PinName 位置正确,往返一致性 | + +--- + +## 2. 已有测试覆盖分析 + +### 2.1 单元测试 (`Code/src/test_pinmap.py`) — 9 个用例,全部通过 + +| 用例 | 覆盖范围 | v1.5 是否受影响 | +|------|---------|----------------| +| `test_4x4_parse` | 4×4 PinMAP 解析 (left/bottom/right/top) | ✅ 已验证 bottom/right Name 位置正确 | +| `test_4x4_validate` | 4×4 PinMAP 验证 | 不受影响 | +| `test_missing_names_warning` | 缺失 Name 警告 | 不受影响 | +| `test_duplicate_numbers` | 重复序号错误 | 不受影响 | +| `test_gap_in_numbers` | 序号不连续错误 | 不受影响 | +| `test_empty_cells` | 空单元格异常 | 不受影响 | +| `test_no_pins` | 无 Pin 数据异常 | 不受影响 | +| `test_12pin_square` | 6×6 12Pin 解析和验证 | 不受影响 | +| `test_f012_pinname_position` | **v1.5 新增** — 5×5 20Pin 往返一致性 | ✅ **v1.5 核心回归测试** | + +### 2.2 集成测试 (`Test/run_tests.py`) — 23 个用例,全部通过 + +| 编号 | 用例 | v1.5 是否受影响 | +|------|------|----------------| +| TC-MAP-001~006 | MAP→List 回归(含错误/警告场景) | ⚠️ F009 影响模板查找逻辑 | +| TC-LM-001~016 | List→MAP 新增(含错误/警告/往返) | ⚠️ F010/F011 影响模板样式应用 | + +### 2.3 已有测试缺口(v1.5 前) + +1. **无模板相关测试** — 现有集成测试仅在 `TC-LM-003` 中使用临时创建的 fake 模板验证 styles.xml 存在,未测试真实的 BallList/BallMAP 模板分离 +2. **无样式正确性验证** — 现有测试仅验证 `styles.xml` 文件存在,未验证字体/边框/填充/对齐/列宽/行高的实际内容 +3. **无模板降级测试** — 未测试模板不存在/解析失败时的优雅降级行为 +4. **无两方向独立模板测试** — 未验证 MAP→List 和 List→MAP 使用不同模板时的隔离性 + +--- + +## 3. 完整测试方案 + +### 3.1 测试分层策略 + +| 层级 | 位置 | 测试什么 | 执行方式 | +|------|------|---------|---------| +| **Unit** | `Code/src/test_pinmap.py` | 纯逻辑测试(解析/验证/布局/往返),不依赖文件系统 | `python3 Code/src/test_pinmap.py` | +| **Integration** | `Test/run_tests.py` | 文件级测试(xlsx 读写/模板加载/端到端),依赖 fixtures/ 和临时文件 | `python3 Test/run_tests.py` | + +### 3.2 测试原则 + +1. **单元测试** (`test_pinmap.py`):纯逻辑测试,不读/写磁盘文件,使用内存中的 cell dict +2. **集成测试** (`run_tests.py`):文件级测试,使用 `Test/fixtures/` 中的真实 .xlsx 文件和临时目录中的动态创建文件 +3. **模板 fixture**:需要准备 `BallList-Template.xlsx` 和 `BallMAP-Template.xlsx` 两个模板 fixture 文件 + +--- + +## 4. F012 — PinName 位置回归测试 + +### 4.1 状态确认 + +**代码当前行为**: +- `pinmap_layout.py::get_name_cell`: bottom → `(r-1, c)`, top → `(r+1, c)` +- `pinmap_parser.py`: bottom name 读自 `(max_row-1, c)`, top name 读自 `(min_row+1, c)` +- 生成与解析使用**相同约定**,往返一致 ✅ + +**F012 测试确认**:当前代码已正确,测试已存在并全部通过。 + +### 4.2 已有回归测试(无需新增) + +| 用例 | 位置 | 覆盖 | +|------|------|------| +| `test_f012_pinname_position` | `test_pinmap.py` | 5×5 20Pin 往返:生成 → 逐个验证四条边 Name 位置 → 解析回 PinList → 验证序号一致性 | + +### 4.3 测试数据 + +``` +test_pinmap.py 中的 4×4 数据已验证: + bottom: numbers at (6,2)=3, (6,3)=4; names at (5,2)=Pin3, (5,3)=Pin4 → max_row-1 ✅ + top: numbers at (1,3)=7, (1,2)=8; names at (2,3)=Pin7, (2,2)=Pin8 → min_row+1 ✅ + +test_f012 5×5 数据已验证: + bottom: names at (4, c) = rows-1 = max_row-1 ✅ + top: names at (2, c) = min_row+1 ✅ + left: names at (r, 1) = c+1 ✅ + right: names at (r, 4) = c-1 ✅ +``` + +### 4.4 F012 测试结论 + +✅ **无需新增测试**。`test_f012_pinname_position` 已充分覆盖 F012 需求,且当前测试全部通过。保持该测试持续运行即可。 + +--- + +## 5. F009 + F010 — 模板分离测试 + +### 5.1 测试场景矩阵 + +| 场景 | BallList-Template | BallMAP-Template | MAP→List 预期 | List→MAP 预期 | +|------|-------------------|------------------|-------------|-------------| +| T-F009-01 | ✅ 存在 | — | 加载 BallList,应用其样式 | (不涉及) | +| T-F009-02 | ❌ 不存在 | — | 日志提示"未检测到",使用默认样式 | (不涉及) | +| T-F009-03 | 存在但损坏 | — | 日志提示"解析失败",使用默认样式 | (不涉及) | +| T-F010-01 | — | ✅ 存在 | (不涉及) | 加载 BallMAP,应用其样式 | +| T-F010-02 | — | ❌ 不存在 | (不涉及) | 日志提示"未检测到",使用默认样式 | +| T-F010-03 | — | 存在但损坏 | (不涉及) | 日志提示"解析失败",使用默认样式 | +| T-F009-04 | ✅ 存在 | ✅ 存在 | 加载 BallList | 加载 BallMAP(各自独立,互不干扰) | + +### 5.2 关键验证点 + +1. **MAP→List 不使用 BallMAP 模板** — 即使 BallMAP-Template.xlsx 存在,MAP→List 也不会加载它 +2. **List→MAP 不使用 BallList 模板** — 即使 BallList-Template.xlsx 存在,List→MAP 也不会加载它 +3. **不加载旧 PinMAP-Template.xlsx** — 即使旧模板存在,两个方向都不加载 + +### 5.3 单元测试:新增到 `test_pinmap.py` + +以下测试**可**新增到 `test_pinmap.py`(纯逻辑,不依赖文件系统): + +#### U-F009-F010-001: `_find_balllist_template_path` 和 `_find_ballmap_template_path` 路径生成 + +```python +def test_template_path_generation(): + """验证两个模板查找函数返回正确的路径格式。""" + import os + from main import _find_balllist_template_path, _find_ballmap_template_path + + # 路径应以项目根目录为基础,包含正确的文件名 + # 注意:这些函数检查文件是否存在,测试环境可能没有这些文件 + # 所以只验证函数可调用且返回类型正确 + result1 = _find_balllist_template_path() + result2 = _find_ballmap_template_path() + + # 返回值要么是 str 要么是 None + assert result1 is None or isinstance(result1, str) + assert result2 is None or isinstance(result2, str) + # 两者应该是不同路径 + if result1 and result2: + assert "BallList" in result1 + assert "BallMAP" in result2 + assert result1 != result2 + + print("✓ test_template_path_generation passed") +``` + +### 5.4 集成测试:新增到 `Test/run_tests.py` + +以下测试需要 `Test/fixtures/` 中的模板文件: + +**Fixture 准备**: + +| 文件 | 用途 | 内容要求 | +|------|------|---------| +| `Test/fixtures/BallList-Template.xlsx` | MAP→List 模板 | 至少包含 fonts(Calibri 12pt, bold), borders(thin), column_widths | +| `Test/fixtures/BallMAP-Template.xlsx` | MAP→List 模板 | 至少包含 fonts(Arial 10pt), borders(medium), row_heights | +| `Test/fixtures/template_corrupt.xlsx` | 损坏模板测试 | 一个非 xlsx 的普通文件伪装为 .xlsx | + +**新增集成测试用例**: + +#### TC-v1.5-001: MAP→List 加载 BallList 模板(模板存在) + +``` +前置: fixtures/BallList-Template.xlsx 存在 +步骤: + 1. 创建 PinMAP 输入(4×4) + 2. 模拟 run_map_to_list 模板加载流程 + 3. 验证 read_template_styles 返回非 None + 4. 验证返回的 TemplateStyle 包含字体信息 +预期: 模板样式成功加载,输出文件包含 styles.xml +``` + +#### TC-v1.5-002: MAP→List 无模板降级(模板不存在) + +``` +前置: 删除根目录的 BallList-Template.xlsx +步骤: + 1. 创建 PinMAP 输入(4×4) + 2. 调用 _find_balllist_template_path() + 3. 验证返回 None +预期: 返回 None,输出使用默认样式 +``` + +#### TC-v1.5-003: List→MAP 加载 BallMAP 模板(模板存在) + +``` +前置: fixtures/BallMAP-Template.xlsx 存在 +步骤: + 1. 创建 5×5 PinList 输入(20 pin) + 2. 模拟 run_list_to_map 模板加载流程 + 3. 验证 read_template_styles 返回非 None + 4. 生成 PinMAP,验证输出包含 styles.xml +预期: 模板样式成功加载,输出文件包含 styles.xml +``` + +#### TC-v1.5-004: List→MAP 无模板降级(模板不存在) + +``` +前置: 删除根目录的 BallMAP-Template.xlsx +步骤: + 1. 创建 5×5 PinList 输入(20 pin) + 2. 调用 _find_ballmap_template_path() + 3. 验证返回 None +预期: 返回 None,输出使用默认样式 +``` + +#### TC-v1.5-005: 两个方向独立使用各自模板 + +``` +前置: BallList-Template.xlsx 和 BallMAP-Template.xlsx 都存在 +步骤: + 1. MAP→List 方向:调用 _find_balllist_template_path(),验证路径包含 "BallList" + 2. List→MAP 方向:调用 _find_ballmap_template_path(),验证路径包含 "BallMAP" + 3. 验证两个路径不同 +预期: 两个方向各自查找各自的模板文件,互不干扰 +``` + +#### TC-v1.5-006: 模板损坏时优雅降级 + +``` +前置: 提供一个损坏的 "template_corrupt.xlsx" +步骤: + 1. 调用 read_template_styles("fixtures/template_corrupt.xlsx") + 2. 验证返回 None(不抛异常) +预期: 返回 None,调用方可继续使用默认样式 +``` + +--- + +## 6. F011 — 模板格式提取式应用测试 + +### 6.1 测试场景 + +F011 核心要求:模板的**格式信息**(字体/边框/填充/对齐/列宽/行高)正确应用到输出文件,但输出文件的**行列结构**由实际 Pin 数量决定。 + +### 6.2 单元测试:新增到 `test_pinmap.py` + +F011 的样式构建逻辑在 `xlsx_writer.py::StyledXLSXWriter` 中,涉及 XML 字符串生成。以下测试可以在不写磁盘文件的情况下验证 XML 内容: + +#### U-F011-001: 无模板时使用默认样式 + +```python +def test_f011_default_styles_xml(): + """F011: 无模板时 _styles_xml() 返回硬编码默认样式。""" + from xlsx_writer import StyledXLSXWriter + + writer = StyledXLSXWriter(style=None) + xml = writer._styles_xml() + + # 验证硬编码默认值的存在 + assert 'Calibri' in xml, "默认字体应为 Calibri" + assert 'thin' in xml or 'style="thin"' in xml, "默认边框应为 thin" + assert 'center' in xml, "默认对齐应为 center" + assert 'cellXfs count="4"' in xml, "应有 4 个 xf" + + print("✓ test_f011_default_styles_xml passed") +``` + +#### U-F011-002: 有模板时使用模板字体 + +```python +def test_f011_template_fonts_in_styles_xml(): + """F011: 有模板时 _styles_xml() 使用模板的字体信息(而非硬编码 Calibri)。""" + from template_reader import TemplateStyle, FontStyle + from xlsx_writer import StyledXLSXWriter + + # 构建一个模板样式:微软雅黑 12pt + bold + style = TemplateStyle() + style.fonts = [ + FontStyle(name="微软雅黑", size=12.0, bold=False, italic=False, color="FF000000"), + FontStyle(name="微软雅黑", size=12.0, bold=True, italic=False, color="FF000000"), + ] + style.fills = [] + style.borders = [] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '0', 'xfId': '0'}, + ] + + writer = StyledXLSXWriter(style=style) + xml = writer._styles_xml() + + assert '微软雅黑' in xml, f"模板字体名应出现在 styles.xml 中\n{xml[:500]}" + assert '12' in xml or '12.0' in xml, f"模板字号 12pt 应出现在 styles.xml 中" + + print("✓ test_f011_template_fonts_in_styles_xml passed") +``` + +#### U-F011-003: 有模板时使用模板边框 + +```python +def test_f011_template_borders_in_styles_xml(): + """F011: 有模板时 _styles_xml() 使用模板的边框样式(而非硬编码 thin)。""" + from template_reader import TemplateStyle, BorderStyle, FontStyle + from xlsx_writer import StyledXLSXWriter + + style = TemplateStyle() + style.fonts = [FontStyle(name="Calibri", size=11.0)] + style.borders = [ + BorderStyle(top="none", bottom="none", left="none", right="none"), + BorderStyle(top="medium", bottom="medium", left="medium", right="medium"), + ] + style.fills = [] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '1', 'xfId': '0', + 'applyBorder': '1'}, + ] + + writer = StyledXLSXWriter(style=style) + xml = writer._styles_xml() + + # 模板的 medium 边框应该存在(不仅仅是 thin) + assert 'medium' in xml, f"模板 medium 边框应出现在 styles.xml 中\n{xml[:800]}" + + print("✓ test_f011_template_borders_in_styles_xml passed") +``` + +#### U-F011-004: 有模板时使用模板填充 + +```python +def test_f011_template_fills_in_styles_xml(): + """F011: 有模板时 _styles_xml() 使用模板的填充色(而非硬编码 FFF0F0F0)。""" + from template_reader import TemplateStyle, FillStyle, FontStyle + from xlsx_writer import StyledXLSXWriter + + style = TemplateStyle() + style.fonts = [FontStyle(name="Calibri", size=11.0)] + style.borders = [] + style.fills = [ + FillStyle(pattern_type="none", fg_color=""), + FillStyle(pattern_type="solid", fg_color="FFFF00"), # 黄色 + ] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '0', 'xfId': '0'}, + {'numFmtId': '0', 'fontId': '0', 'fillId': '1', 'borderId': '0', 'xfId': '0', + 'applyFill': '1'}, + ] + + writer = StyledXLSXWriter(style=style) + xml = writer._styles_xml() + + assert 'FFFF00' in xml, f"模板黄色填充应出现在 styles.xml 中\n{xml[:800]}" + + print("✓ test_f011_template_fills_in_styles_xml passed") +``` + +#### U-F011-005: 输出行列由实际 Pin 决定(不复制模板行列结构) + +```python +def test_f011_output_dims_determined_by_pins(): + """F011: 输出文件的 dim 由实际 Pin 数量决定,不复制模板的行列结构。 + + 即使模板有 100 行列定义,输出仍只包含实际 Pin 数据的行列。 + """ + from template_reader import TemplateStyle, FontStyle + from xlsx_writer import StyledXLSXWriter + + style = TemplateStyle() + style.fonts = [FontStyle(name="Calibri", size=11.0)] + style.column_widths = {i: 20.0 for i in range(100)} # 模板有 100 列 + style.row_heights = {i: 30.0 for i in range(200)} # 模板有 200 行 + style.fills = [] + style.borders = [] + style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '0', 'xfId': '0'}, + ] + + # 仅输出 2 行 3 列的数据(模拟 2×2 PinMAP + A1) + data = { + 'A1': 'QFP-8', + 'A2': '1', 'B2': 'Pin1', + 'A3': '2', 'B3': 'Pin2', + } + + writer = StyledXLSXWriter(style=style) + sheet_xml = writer._sheet_xml(data) + + # dim 应该反映实际数据范围(A1:C3),而非模板的 100 列 + assert 'dimension ref="A1:C' in sheet_xml or 'dimension ref="A1:C3"' in sheet_xml, \ + f"dim 应由实际数据决定,不应包含模板的 100 列\n{sheet_xml[:500]}" + + # 不应出现 row r="201"(模板的第 200 行) + assert 'row r="201"' not in sheet_xml, "不应包含模板的多余行" + + print("✓ test_f011_output_dims_determined_by_pins passed") +``` + +### 6.3 集成测试:新增到 `Test/run_tests.py` + +#### TC-v1.5-007: 模板字体应用到输出文件 + +``` +前置: fixtures/BallMAP-Template.xlsx 使用微软雅黑 14pt +步骤: + 1. 用该模板生成 5×5 PinMAP 输出 + 2. 解压输出 xlsx,读取 xl/styles.xml + 3. 验证 fonts 部分包含 "微软雅黑" 和 size=14 +预期: 输出 styles.xml 包含模板字体定义 +``` + +#### TC-v1.5-008: 模板列宽应用到输出文件 + +``` +前置: fixtures/BallList-Template.xlsx 中 A 列宽=25, B 列宽=18 +步骤: + 1. 用该模板生成 PinList 输出 + 2. 解压输出 xlsx,读取 xl/worksheets/sheet1.xml + 3. 验证 cols 元素中 A 列 width=25, B 列 width=18 +预期: 输出列宽与模板一致 +``` + +#### TC-v1.5-009: 模板行高应用到输出文件 + +``` +前置: fixtures/BallMAP-Template.xlsx 中行高=25 +步骤: + 1. 用该模板生成 3×3 PinMAP 输出 + 2. 解压输出 xlsx,读取 xl/worksheets/sheet1.xml + 3. 验证 row 元素包含 ht=25 +预期: 输出行高与模板一致 +``` + +#### TC-v1.5-010: 两个方向使用不同模板各自的格式 + +``` +前置: + - BallList-Template.xlsx 字体=楷体 12pt + - BallMAP-Template.xlsx 字体=宋体 14pt +步骤: + 1. MAP→List 方向:用 BallList 模板生成 PinList,验证输出字体=楷体 12pt + 2. List→MAP 方向:用 BallMAP 模板生成 PinMAP,验证输出字体=宋体 14pt + 3. 验证两个输出文件的字体不同 +预期: 两个方向的输出各自使用对应模板的字体 +``` + +--- + +## 7. F009/F010/F011 集成测试 + +### 7.1 端到端集成测试 + +#### TC-v1.5-011: 完整往返 + 模板隔离 (MAP→List→MAP) + +``` +前置: BallList-Template.xlsx 和 BallMAP-Template.xlsx 都存在且格式不同 +步骤: + 1. 使用 BallList 模板,执行 sample_4x4.xlsx → PinList + 2. 验证 PinList 输出包含 BallList 模板的格式特征 + 3. 使用 BallMAP 模板,执行 PinList → PinMAP + 4. 验证 PinMAP 输出包含 BallMAP 模板的格式特征 + 5. 验证往返后的 PinMAP 与原 PinMAP 数据一致(忽略格式差异) +预期: + - 往返数据完全一致(引脚序号/名称/封装信息) + - 中间 PinList 使用 BallList 模板格式 + - 最终 PinMAP 使用 BallMAP 模板格式 +``` + +#### TC-v1.5-012: 无模板完整流程 + +``` +前置: 根目录没有 BallList-Template.xlsx 也没有 BallMAP-Template.xlsx +步骤: + 1. 执行 MAP→List 转换 + 2. 执行 List→MAP 转换 + 3. 验证两个输出文件都能正常生成且数据正确 + 4. 验证两个输出文件使用默认样式(Calibri 11pt) +预期: 无模板情况下正常降级,输出使用默认样式,数据正确 +``` + +--- + +## 8. 边界与异常测试 + +### 8.1 模板边界测试 + +| 编号 | 场景 | 预期行为 | 测试级别 | +|------|------|---------|---------| +| TC-BND-001 | 模板 fonts 为空列表 | 回退到默认字体 | Unit | +| TC-BND-002 | 模板 borders 为空列表 | 回退到默认边框(thin) | Unit | +| TC-BND-003 | 模板 fills 为空列表 | 回退到默认填充 | Unit | +| TC-BND-004 | 模板 cell_xfs 为空列表 | 回退到默认 cellXfs(4 个硬编码 xf) | Unit | +| TC-BND-005 | 模板 column_widths 为空 dict | 使用默认列宽 8.0 | Unit | +| TC-BND-006 | 模板 row_heights 为空 dict | 不使用自定义行高(使用 Excel 默认) | Unit | +| TC-BND-007 | 模板字体 color 缺少 FF 前缀 | xlsx_writer 自动补全 | Unit | +| TC-BND-008 | 模板填充 fg_color 缺少 FF 前缀 | xlsx_writer 自动补全 | Unit | +| TC-BND-009 | 模板中缺失 styles.xml | read_template_styles 返回 None | Unit | +| TC-BND-010 | 模板中缺失 sheet1.xml | column_widths/row_heights 为空 | Unit | + +### 8.2 边界场景集成测试 + +#### TC-v1.5-013: 模板只有字体、无边框/填充 + +``` +前置: 准备一个只有 fonts 定义的极简模板 +步骤: + 1. 加载模板样式 + 2. 验证 fonts 正确提取 + 3. 验证 borders/fills 使用默认值 + 4. 生成的输出文件可正常打开 +预期: 字体来自模板,边框/填充使用默认值,文件可正常打开 +``` + +#### TC-v1.5-014: 模板列宽少于输出列数 + +``` +前置: 模板定义 3 列宽,但输出需要 6 列 +步骤: + 1. 加载模板(定义 A-C 列宽) + 2. 生成 5×5(6 列) PinMAP + 3. 验证模板定义的列使用模板宽度,额外的列使用默认 8.0 +预期: 列宽正确扩展,无异常 +``` + +--- + +## 9. 测试执行计划 + +### 9.1 新增单元测试(添加到 `test_pinmap.py`) + +| 优先级 | 编号 | 测试名 | 简述 | +|--------|------|--------|------| +| P0 | U-F009-F010-001 | `test_template_path_generation` | 验证模板路径格式正确且互不相同 | +| P0 | U-F011-001 | `test_f011_default_styles_xml` | 无模板时使用默认样式 | +| P0 | U-F011-002 | `test_f011_template_fonts_in_styles_xml` | 模板字体应用到 styles.xml | +| P1 | U-F011-003 | `test_f011_template_borders_in_styles_xml` | 模板边框应用到 styles.xml | +| P1 | U-F011-004 | `test_f011_template_fills_in_styles_xml` | 模板填充应用到 styles.xml | +| P0 | U-F011-005 | `test_f011_output_dims_determined_by_pins` | 输出 dim 由 Pin 数决定 | +| P1 | U-BND-001 | `test_template_empty_fonts_fallback` | 空 fonts 回退 | +| P1 | U-BND-007 | `test_template_color_prefix_auto_fix` | FF 前缀补全 | +| P1 | U-BND-009 | `test_template_no_styles_xml` | 缺失 styles.xml 降级 | + +### 9.2 新增集成测试(添加到 `Test/run_tests.py`) + +| 优先级 | 编号 | 测试名 | 简述 | 需要 Fixture | +|--------|------|--------|------|------------| +| P0 | TC-v1.5-001 | MAP→List 加载 BallList 模板 | 模板存在时正确加载 | BallList-Template.xlsx | +| P0 | TC-v1.5-002 | MAP→List 无模板降级 | 模板不存在时优雅降级 | 无 | +| P0 | TC-v1.5-003 | List→MAP 加载 BallMAP 模板 | 模板存在时正确加载 | BallMAP-Template.xlsx | +| P0 | TC-v1.5-004 | List→MAP 无模板降级 | 模板不存在时优雅降级 | 无 | +| P0 | TC-v1.5-005 | 两个方向独立模板 | 各自使用各自的模板 | 两个模板 | +| P1 | TC-v1.5-006 | 模板损坏优雅降级 | 损坏模板不抛异常 | template_corrupt.xlsx | +| P1 | TC-v1.5-007 | 模板字体应用到输出 | 输出文件含模板字体 | 特殊字体模板 | +| P1 | TC-v1.5-008 | 模板列宽应用到输出 | 输出列宽=模板列宽 | 特殊列宽模板 | +| P1 | TC-v1.5-009 | 模板行高应用到输出 | 输出行高=模板行高 | 特殊行高模板 | +| P1 | TC-v1.5-010 | 两个方向各自格式 | 两个方向格式独立 | 两个不同格式模板 | +| P1 | TC-v1.5-011 | 完整往返+模板隔离 | MAP→List→MAP 数据一致 | 两个模板 | +| P1 | TC-v1.5-012 | 无模板完整流程 | 无模板正常降级 | 无 | +| P2 | TC-v1.5-013 | 极简模板 | 只有字体的模板 | 极简模板 | +| P2 | TC-v1.5-014 | 列宽扩展 | 模板列宽少于输出列数 | 窄模板 | + +--- + +## 10. Fixture 准备清单 + +### 10.1 需要创建的 Fixture 文件 + +| 文件 | 放置位置 | 用途 | 关键内容 | +|------|---------|------|---------| +| `BallList-Template.xlsx` | `Test/fixtures/` | MAP→List 模板 | 字体=楷体 12pt, A列宽=25, B列宽=18, 边框=thin, 对齐=center | +| `BallMAP-Template.xlsx` | `Test/fixtures/` | List→MAP 模板 | 字体=宋体 14pt, 行高=25, 边框=medium, 填充=淡黄 FFFFFF00 | +| `template_corrupt.xlsx` | `Test/fixtures/` | 损坏模板测试 | 一个无效的 ZIP 文件或文本文件伪装为 .xlsx | +| `template_minimal.xlsx` | `Test/fixtures/` | 极简模板测试 | 只有 1 个 font 定义,无 borders/fills | +| `template_narrow.xlsx` | `Test/fixtures/` | 列宽扩展测试 | 只定义 3 列宽(A-C),但测试输出 6 列 | + +### 10.2 集成测试时的模板放置策略 + +集成测试需要能临时将模板放到正确位置。建议方案: + +**方案 A(推荐)**:在 `run_tests.py` 中使用 `tempfile.mkdtemp` 创建临时目录,将 fixture 模板复制为 `BallList-Template.xlsx` / `BallMAP-Template.xlsx`,然后通过 `os.chdir` 或修改 `sys.path` 让 main.py 的模板查找逻辑找到它们。 + +**方案 B**:在 `run_tests.py` 中直接调用底层函数(`read_template_styles`, `_find_balllist_template_path`),不经过 main.py 的路径查找,而是直接传入 fixture 路径。 + +推荐 **方案 B**(更简洁),因为已有测试也是直接调用底层函数。 + +### 10.3 Fixture 创建方法 + +使用 `xlsx_writer.py::write_xlsx_with_style` 创建带特定格式的模板文件: + +```python +# 创建 BallList-Template.xlsx +from xlsx_writer import StyledXLSXWriter +from template_reader import TemplateStyle, FontStyle, BorderStyle, FillStyle + +style = TemplateStyle() +style.fonts = [ + FontStyle(name="楷体", size=12.0, bold=False, color="FF000000"), + FontStyle(name="楷体", size=12.0, bold=True, color="FF000000"), +] +style.borders = [ + BorderStyle(top="none", bottom="none", left="none", right="none"), + BorderStyle(top="thin", bottom="thin", left="thin", right="thin"), +] +style.fills = [FillStyle(pattern_type="none")] +style.cell_xfs = [ + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '0', 'xfId': '0'}, + {'numFmtId': '0', 'fontId': '0', 'fillId': '0', 'borderId': '1', 'xfId': '0', + 'applyBorder': '1', 'hAlign': 'center', 'vAlign': 'center'}, +] +style.column_widths = {0: 25.0, 1: 18.0} +style.row_heights = {} + +# 创建 PinList 模板数据(2 行示例数据) +data = {'A1': '封装信息', 'A2': 'Pin1', 'B2': '1', 'A3': 'Pin2', 'B3': '2'} + +writer = StyledXLSXWriter(style) +writer.write(data, "fixtures/BallList-Template.xlsx") +``` + +--- + +## 11. 预期工作量 + +| 阶段 | 内容 | 预估时间 | +|------|------|---------| +| Fixture 准备 | 创建 5 个模板 fixture 文件 | 30 min | +| 单元测试 | 新增约 10 个单元测试到 `test_pinmap.py` | 1 hr | +| 集成测试 | 新增约 14 个集成测试到 `run_tests.py` | 1.5 hr | +| 回归验证 | 运行全部测试确认无回归 | 15 min | +| 文档更新 | 更新测试报告 | 10 min | +| **总计** | | **~3.5 hr** | + +--- + +## 12. 测试通过标准 + +| 条件 | 要求 | +|------|------| +| 现有 9 个单元测试 | 全部通过 | +| 现有 23 个集成测试 | 全部通过 | +| 新增 ~10 个单元测试 | 全部通过 | +| 新增 ~14 个集成测试 | 全部通过 | +| F012 往返测试 (`test_f012_pinname_position`) | 持续通过 | +| F009/F010 模板分离 | 两个方向使用各自模板,互不干扰 | +| F011 模板格式提取 | 字体/边框/填充/对齐/列宽/行高从模板正确应用 | +| 无模板场景 | 优雅降级使用默认样式,不抛异常 | +| 损坏模板场景 | 优雅降级为 None,不抛异常 | + +--- + +## 13. 总结 + +### 13.1 测试设计决策 + +| 决策 | 说明 | +|------|------| +| F012 不再新增测试 | `test_f012_pinname_position` 已充分覆盖,代码行为已确认正确 | +| F009/F010 模板分离测试侧重降级 | 核心风险在于模板不存在/解析失败时的行为,而非正常路径 | +| F011 样式测试分两层 | 单元层验证 XML 生成,集成层验证最终文件内容 | +| 单元测试不依赖文件系统 | 使用内存中的 `TemplateStyle` 对象直接构造测试数据 | +| 集成测试使用 fixture 文件 | 由 test-executor 预先创建模板 fixture,再运行测试 | + +### 13.2 测试覆盖矩阵 + +``` + F012 F009 F010 F011 边界 集成 +现有 test_pinmap.py ✅ — — — — — +现有 run_tests.py — — — — — ✅ +新增 unit tests — ✅ ✅ ✅ ✅ — +新增 integration tests— ✅ ✅ ✅ ✅ ✅ +``` + +### 13.3 下一步 + +1. **test-executor** 按本方案执行 Fixture 准备(创建 5 个模板文件) +2. **test-executor** 按优先级 P0 → P1 → P2 实施测试代码 +3. 运行完整测试套件验证 +4. 生成 v1.5.0 最终测试报告 + +--- + +*测试方案结束 — 等待 test-executor 执行* \ No newline at end of file diff --git a/Test/test_report.md b/Test/test_report.md index a1952b5..08f3f4e 100644 --- a/Test/test_report.md +++ b/Test/test_report.md @@ -1,18 +1,51 @@ -# PinMAP ↔ PinList 双向转换器 测试报告 +# PinMAP ↔ PinList 双向转换器 测试报告 (v1.5.0) -> **日期**: 2026-06-01 -> **测试类型**: 集成测试 + 端到端测试 +> **版本**: v1.5.0 +> **日期**: 2026-06-06 +> **测试类型**: 单元测试 + 集成测试 + 端到端测试 > **测试环境**: Python 3.x, Linux x64 --- +## v1.5.0 变更覆盖 + +v1.5.0 引入三项核心变更: +- **F009**: MAP→List 使用 BallList-Template.xlsx(独立模板) +- **F010**: List→MAP 使用 BallMAP-Template.xlsx(独立模板) +- **F011**: 模板格式提取式应用(字体/边框/填充/对齐/列宽/行高) +- **F012**: PinName 位置确认(bottom=max_row-1, top=min_row+1) + +## 测试覆盖矩阵 + +| 特性 | 单元测试 | 集成测试 | 状态 | +|------|---------|---------|------| +| F009 — BallList 模板加载 | ✅ `test_template_path_generation` | ✅ TC-v1.5-001/002/005 | ✅ | +| F010 — BallMAP 模板加载 | ✅ `test_template_path_generation` | ✅ TC-v1.5-003/004/005 | ✅ | +| F011 — 模板字体应用 | ✅ `test_f011_template_fonts_in_styles_xml` | ✅ TC-v1.5-007/010/013 | ✅ | +| F011 — 模板边框应用 | ✅ `test_f011_template_borders_in_styles_xml` | ✅ TC-v1.5-007/010 | ✅ | +| F011 — 模板填充应用 | ✅ `test_f011_template_fills_in_styles_xml` | ✅ TC-v1.5-010 | ✅ | +| F011 — 默认样式降级 | ✅ `test_f011_default_styles_xml` | ✅ TC-v1.5-002/004/012 | ✅ | +| F011 — 输出 dim 由 Pin 决定 | ✅ `test_f011_output_dims_determined_by_pins` | ✅ TC-v1.5-014 | ✅ | +| F011 — 列宽应用 | — | ✅ TC-v1.5-008/014 | ✅ | +| F011 — 行高应用 | — | ✅ TC-v1.5-009 | ✅ | +| F012 — PinName 位置 | ✅ `test_f012_pinname_position` | — | ✅ | +| 损坏模板优雅降级 | — | ✅ TC-v1.5-006 | ✅ | +| 极简模板 | — | ✅ TC-v1.5-013 | ✅ | +| 无模板完整流程 | — | ✅ TC-v1.5-012 | ✅ | +| 完整往返+模板隔离 | — | ✅ TC-v1.5-011 | ✅ | +| 空 fonts/样式回退 | ✅ `test_template_empty_fonts_fallback` | — | ✅ | +| FF 颜色前缀补全 | ✅ `test_template_color_prefix_auto_fix` | — | ✅ | +| 缺失 styles.xml 降级 | ✅ `test_template_no_styles_xml` | — | ✅ | + ## 测试概览 | 类别 | 用例数 | 通过 | 失败 | |------|--------|------|------| -| MAP→List 回归 | 6 | 6 | 0 | -| List→MAP 新增 | 17 | 17 | 0 | -| **总计** | **23** | **23** | **0** | +| 单元测试 (test_pinmap.py) | **18** | **18** | **0** | +| MAP->List 回归 | 6 | 6 | 0 | +| List->MAP 新增 | 17 | 17 | 0 | +| v1.5 模板/样式集成 | 14 | 14 | 0 | +| **总计** | **55** | **55** | **0** | --- @@ -112,6 +145,64 @@ - **结果**: ✅ 通过 - **详情**: 正确报错: A1 单元格为空,无法获取封装信息 +## Part 3: v1.5 模板/样式集成测试 + +### TC-v1.5-001: MAP->List 加载 BallList 模板 +- **结果**: ✅ 通过 +- **详情**: 模板加载成功: fonts=2, borders=2, width_A=25.0 + +### TC-v1.5-002: MAP->List 无模板降级 +- **结果**: ✅ 通过 +- **详情**: 无模板文件时优雅返回 None + +### TC-v1.5-003: List->MAP 加载 BallMAP 模板 +- **结果**: ✅ 通过 +- **详情**: 模板加载成功: fonts=2, borders=2, row_height=25.0 + +### TC-v1.5-004: List->MAP 无模板降级 +- **结果**: ✅ 通过 +- **详情**: 无模板文件时优雅返回 None + +### TC-v1.5-005: 两个方向独立使用各自模板 +- **结果**: ✅ 通过 +- **详情**: 两个模板独立: BL fonts=2, BM fonts=2 + +### TC-v1.5-006: 模板损坏优雅降级 +- **结果**: ✅ 通过 +- **详情**: 损坏模板优雅返回 None + +### TC-v1.5-007: 模板字体应用到输出文件 +- **结果**: ✅ 通过 +- **详情**: 输出 styles.xml 包含模板字体(宋体 14pt) + +### TC-v1.5-008: 模板列宽应用到输出文件 +- **结果**: ✅ 通过 +- **详情**: 列宽验证通过: A=25.0, B=18.0 + +### TC-v1.5-009: 模板行高应用到输出文件 +- **结果**: ✅ 通过 +- **详情**: 行高验证通过: ht=25 + +### TC-v1.5-010: 两个方向不同模板各自的格式 +- **结果**: ✅ 通过 +- **详情**: 两个方向输出字体不同: BL->楷体, BM->宋体 + +### TC-v1.5-011: 完整往返+模板隔离 +- **结果**: ✅ 通过 +- **详情**: 往返成功: 12 pins, 楷体->PinList, 宋体->PinMAP + +### TC-v1.5-012: 无模板完整流程 +- **结果**: ✅ 通过 +- **详情**: 无模板完整流程正常 + +### TC-v1.5-013: 极简模板(只有字体) +- **结果**: ✅ 通过 +- **详情**: 极简模板: font=Courier New + +### TC-v1.5-014: 列宽扩展 +- **结果**: ✅ 通过 +- **详情**: 列宽扩展正确: A=15.0, B=12.0, C=10.0, D=8.0, E=8.0 + --- ## 结论 diff --git a/docs/modification-assessment-v1.5.md b/docs/modification-assessment-v1.5.md new file mode 100644 index 0000000..09115be --- /dev/null +++ b/docs/modification-assessment-v1.5.md @@ -0,0 +1,880 @@ +# PinMAP ↔ PinList 双向转换器 — v1.5.0 修改需求评估 + +> **版本**: v1.5.0 +> **日期**: 2026-06-06 +> **评估人**: 脚本架构师 (Script Architect) +> **状态**: 待审批 +> **变更**: 1 个 P0 Bug 修复 + 3 个 P1 模板分离功能(F009~F012) + +--- + +## 1. 修改需求总览 + +| 编号 | 类型 | 标题 | 优先级 | 复杂度 | 依赖 | +|------|------|------|--------|--------|------| +| F012 | Bug修复 | 修复 PinMAP 生成中上/下边 PinName 位置 | **P0** | 低 | 无 | +| F009 | 功能 | MAP→List 使用 balllist 模板 | P1 | 中 | 无 | +| F010 | 功能 | List→MAP 使用 ballmap 模板 | P1 | 中 | 无 | +| F011 | 功能 | 模板格式提取式应用 | P1 | 中 | F009, F010 | + +--- + +## 2. 当前代码状态分析 + +### 2.1 代码库结构(v1.4.x 基线) + +``` +pinmap-to-pinlist/ +├── run.bat +├── Code/ +│ ├── src/ +│ │ ├── main.py # ✏️ 需修改 (F009/F010/F011) +│ │ ├── file_selector.py # (不变) +│ │ ├── models.py # (不变) +│ │ ├── pinlist_generator.py # (不变) +│ │ ├── pinlist_parser.py # (不变) +│ │ ├── pinlist_validator.py # (不变) +│ │ ├── pinmap_generator.py # (不变/需确认 F012 影响) +│ │ ├── pinmap_layout.py # ✏️ 可能需修改 (F012) +│ │ ├── pinmap_parser.py # (不变) +│ │ ├── template_reader.py # ✏️ 可能需修改 (F011) +│ │ ├── utils.py # (不变) +│ │ ├── validator.py # (不变) +│ │ ├── xls_reader.py # (不变) +│ │ ├── xlsx_reader.py # (不变) +│ │ ├── xlsx_writer.py # (不变/需确认 F011 影响) +│ │ └── test_pinmap.py # ✏️ 需更新 (F012) +│ └── docs/ +│ ├── architecture-design.md +│ ├── modification-assessment.md +│ ├── QUICKSTART.md +│ ├── README.md +│ ├── RELEASE.md +│ └── team.md +├── docs/ +│ ├── bugs.md +│ ├── features.md +│ ├── modification-assessment-v1.3.md +│ ├── requirements.md +│ └── tasks.md +├── Test/ +│ ├── fixtures/ +│ │ ├── sample_4x4.xlsx +│ │ ├── sample_rect.xlsx +│ │ ├── error_*.xlsx +│ │ └── warning_missing.xlsx +│ ├── run_tests.py +│ └── test_report.md +└── Releases/ +``` + +### 2.2 现有模板机制 + +当前代码(v1.4.x)使用**单一模板文件** `PinMAP-Template.xlsx`(位于项目根目录): + +```python +# main.py → _find_template_path() +# 查找根目录下的 PinMAP-Template.xlsx +def _find_template_path() -> str | None: + src_dir = os.path.dirname(os.path.abspath(__file__)) + root_dir = os.path.dirname(os.path.dirname(src_dir)) + template_path = os.path.join(root_dir, "PinMAP-Template.xlsx") + ... +``` + +**当前行为**: +- `run_map_to_list()`(MAP→List)和 `run_list_to_map()`(List→MAP)都查找同一个 `PinMAP-Template.xlsx` +- 两个方向共用同一个模板文件 +- v1.5.0 需求:将两个方向的模板分离 + +### 2.3 各模块当前实现要点 + +#### `main.py` — 入口流程编排 + +```python +# 模板查找:单一模板 +def _find_template_path() -> str | None: + """查找 PinMAP-Template.xlsx""" + +# run_map_to_list(): MAP→List 流程 +# 使用 _find_template_path() 读取模板 → 应用到 PinList 输出 + +# run_list_to_map(): List→MAP 流程 +# 使用 _find_template_path() 读取模板 → 应用到 PinMAP 输出 +``` + +**关键观察**:两个方向都通过 `_find_template_path()` 查找同一模板。v1.5.0 需要分离。 + +#### `pinmap_layout.py` — PinMAP 布局计算 + Name 坐标 + +```python +# 单元格坐标体系(0-based): +# 左边: 序号在 (r, 0), Name 在 (r, c+1) = (r, 1) +# 下边: 序号在 (rows, c), Name 在 (r-1, c) = (rows-1, c) +# 右边: 序号在 (r, cols), Name 在 (r, c-1) = (r, cols-1) +# 上边: 序号在 (1, c), Name 在 (r+1, c) = (2, c) + +def get_name_cell(num_cell, edge_name): + if edge_name == "left": return (r, c+1) # Name 右侧 + elif edge_name == "bottom": return (r-1, c) # Name 上方 + elif edge_name == "right": return (r, c-1) # Name 左侧 + elif edge_name == "top": return (r+1, c) # Name 下方 +``` + +**关于 F012 的关键分析**(详见第 3.1 节): + +| 边 | 当前 Name 位置 | 相对序号 | F012 声称"当前" | F012 声称"应改为" | +|----|---------------|---------|----------------|-----------------| +| bottom | `(r-1, c)` = max_row-1 | Name 在序号**上方** | min_row+1 | max_row-1 | +| top | `(r+1, c)` = min_row+1 | Name 在序号**下方** | max_row-1 | min_row+1 | + +**结论**:当前代码实际行为已经符合 F012 的"应改为"目标(bottom Name 在 max_row-1,top Name 在 min_row+1)。F012 描述中的"当前"状态可能指向旧版本代码或使用不同坐标基准的描述。详见 3.1 节分析。 + +#### `pinmap_generator.py` — PinMAP 单元格数据构建 + +```python +def generate_pinmap(entries, rows, cols, package_info, + template_style=None, output_path=None): + # 1. 计算布局 → layout (dict[str, EdgePins]) + # 2. 先写入 PinName 单元格 + # 3. 再写入序号单元格(后可覆盖同名单元格) + # 4. 写入文件(模板样式或默认样式) +``` + +#### `template_reader.py` — 模板样式提取 + +```python +# 关键能力: +# - 解析 xl/styles.xml → fonts, fills, borders, cellXfs +# - 解析 sheet1.xml → column_widths, row_heights +# - 优雅降级:模板不存在/解析失败 → 返回 None + +@dataclass +class TemplateStyle: + fonts: list[FontStyle] + borders: list[BorderStyle] + fills: list[FillStyle] + cell_xfs: list[dict] # xf index → {fontId, borderId, fillId, alignment} + column_widths: dict[int, float] + row_heights: dict[int, float] +``` + +#### `xlsx_writer.py` — XLSX 输出(含样式) + +```python +# StyledXLSXWriter — 生成含 styles.xml 的 xlsx +# _styles_xml(): 读取模板字体/填充/边框 → 构建 styles.xml +# 当前实现:使用硬编码样式(模板字体仅作参考,主体样式内置) +# _sheet_xml(): 应用列宽/行高 + 单元格样式索引 +# style_idx: 0=default, 1=centered+border, 2=bold(A1), 3=fill +``` + +**关键观察**:`StyledXLSXWriter._styles_xml()` 目前是**硬编码样式**(内置字体、边框定义),仅从模板读取字体名称/大小作为参考。列宽和行高从模板的**实际行列**读取,但会按输出数据的实际行列扩展。 + +--- + +## 3. 逐项修改方案 + +--- + +### 3.1 F012: 修复 PinMAP 生成中上/下边 PinName 位置 + +#### 3.1.1 需求分析 + +**F012 描述原文**: +> 修复 PinMAP 生成中上/下边 PinName 位置 +> - 当前:下边 Name 在 min_row+1,上边 Name 在 max_row-1 +> - 应改为:下边 Name 在 max_row-1,上边 Name 在 min_row+1 + +**4×4 参考示例**: +``` +A4:1, A5:2, B4:Pin1, B5:Pin2 (上边) +C7:3, D7:4, C6:Pin3, D6:Pin4 (右边) +F5:5, F4:6, E5:Pin5, E4:Pin6 (下边) +D2:7, C2:8, D3:Pin7, C3:Pin8 (左边) +``` + +#### 3.1.2 代码现状追踪 + +**当前 `get_name_cell` 实现**: + +```python +def get_name_cell(num_cell, edge_name): + r, c = num_cell + if edge_name == "left": return (r, c+1) # Name 在序号右侧 + elif edge_name == "bottom": return (r-1, c) # Name 在序号上方 (max_row-1) + elif edge_name == "right": return (r, c-1) # Name 在序号左侧 + elif edge_name == "top": return (r+1, c) # Name 在序号下方 (min_row+1) +``` + +**当前 `calculate_layout` 单元格坐标**: + +```python +# 下边:序号在 (rows, c),即 max_row +# → get_name_cell 返回 (rows-1, c) = max_row-1 ← 上方 +# +# 上边:序号在 (1, c),即 min_row +# → get_name_cell 返回 (2, c) = min_row+1 ← 下方 +``` + +#### 3.1.3 关键发现:代码可能已经正确 + +将 F012 的"应改为"目标与当前代码对比: + +| 边 | F012"应改为"目标 | 当前代码实际位置 | 是否一致 | +|----|-----------------|-----------------|---------| +| 下边 (bottom) | max_row-1 | `r-1` = rows-1 = max_row-1 | ✅ 一致 | +| 上边 (top) | min_row+1 | `r+1` = 1+1 = min_row+1 | ✅ 一致 | + +**`test_pinmap.py` 中的 4×4 测试数据验证**: + +```python +# Test data (0-based): +# bottom edge: numbers at (6,2)=3, (6,3)=4; names at (5,2)=Pin3, (5,3)=Pin4 +# → max_row=6, names at row 5 = max_row-1 ✓ +# top edge: numbers at (1,3)=7, (1,2)=8; names at (2,3)=Pin7, (2,2)=Pin8 +# → min_row=1, names at row 2 = min_row+1 ✓ +``` + +**该测试在当前代码中已通过**,表明当前 `get_name_cell` 返回值与测试数据一致。 + +#### 3.1.4 可能的问题场景 + +如果确实存在问题,以下场景需排查: + +1. **PinMAP 解析方向**:`pinmap_parser.py` 解析 PinMAP 时,底边 Name 读自 `max_row-1`,顶边 Name 读自 `min_row+1`。这与生成方向一致。但如果解析时使用了错误的位置假设,则来回转换会导致 Name 错位。 + +2. **边名称语义混淆**:F012 描述中的 `(上边)` `(右边)` `(下边)` `(左边)` 标签可能使用了不同的约定(例如,该标签可能对应的是"Name 边的位置"而非"序号所在边")。 + +3. **网格区域偏移**:如果 `A1` 被保留为封装信息,网格区域从第 2 行开始(1-based → 0-based row=1),则 `min_row` 和 `max_row` 的起始值需要重新校准。 + +#### 3.1.5 修改方案 + +**方案 A:确认代码已正确,仅添加回归测试** + +如果代码已正确,则: +1. 不修改 `pinmap_layout.py` +2. 在 `test_pinmap.py` 中增加显式的上/下边 Name 位置验证测试 +3. 更新测试覆盖率 + +**方案 B:按 F012 描述修改(如果确定存在 Bug)** + +如果确实需要交换,修改 `get_name_cell`: + +```python +# 修改前: +elif edge_name == "bottom": return (r-1, c) # Name 在序号上方 +elif edge_name == "top": return (r+1, c) # Name 在序号下方 + +# 修改后(交换 bottom/top 的 Name 位置): +elif edge_name == "bottom": return (r+1, c) # Name 移到序号下方 +elif edge_name == "top": return (r-1, c) # Name 移到序号上方 +``` + +**但此修改会导致现有 `test_4x4_parse` 测试失败**,因为测试数据中 bottom Name 在 `max_row-1`。 + +**方案 C:仅修改 `pinmap_parser.py` 的 Name 读取位置** + +如果问题是解析方向(MAP→List)使用的位置不正确: +修改 `pinmap_parser.py` 中 bottom/top 的 Name 查找行号。 + +#### 3.1.6 建议 + +**强烈建议在实施前与需求方确认具体的 Bug 表现**。基于代码分析: + +| 事实 | 结论 | +|------|------| +| `get_name_cell` 中 bottom Name 在 max_row-1 | 符合 F012 的"应改为" | +| `get_name_cell` 中 top Name 在 min_row+1 | 符合 F012 的"应改为" | +| 4×4 测试已通过 | 代码内部一致 | +| `pinmap_parser.py` 使用相同约定 | 读写一致 | +| F012 描述中的"当前"与代码不符 | 可能存在描述误差 | + +**实施步骤**(按优先级): + +1. **先确认问题**:使用实际的 4×4 PinMAP 输入文件,运行完整的 PinList→PinMAP 转换,检查输出 +2. **定位差异**:对比输出与预期,定位是 `get_name_cell` 还是 `pinmap_parser` 的差异 +3. **修改代码**:根据确认结果修改对应的函数 +4. **更新测试**:同步更新 `test_pinmap.py` 中的测试数据和断言 + +**影响范围**: + +| 文件 | 修改内容 | 可能性 | +|------|---------|--------| +| `pinmap_layout.py` | 修改 `get_name_cell` 的 bottom/top 逻辑 | 低(可能需要确认) | +| `test_pinmap.py` | 更新测试数据/断言 | 中 | +| `pinmap_parser.py` | 修改 Name 读取行号 | 低 | + +**风险评估**: + +| 风险 | 影响 | 概率 | 缓解措施 | +|------|------|------|---------| +| 修改后破坏往返转换一致性 | **高** | 中 | 运行完整的 MAP→List→MAP 往返测试 | +| 修改后破坏现有用户输出 | 中 | 低 | 确认用户实际使用场景 | +| 与需求方沟通不足导致反复修改 | 中 | 中 | **先确认再改** | + +**工作量**:0.5–1 小时(含需求确认) + +--- + +### 3.2 F009: MAP→List 使用 balllist 模板 + +#### 3.2.1 需求 + +> PinMAP→PinList 转换方向查找并使用 `BallList-Template.xlsx`,不再共用 PinMAP 模板 + +**变更前**:`run_map_to_list()` 使用 `_find_template_path()` → `PinMAP-Template.xlsx` +**变更后**:`run_map_to_list()` 查找并使用 `BallList-Template.xlsx` + +#### 3.2.2 影响范围 + +仅在 `main.py` 中修改模板查找逻辑,核心转换代码不受影响。 + +**涉及文件**: + +| 文件 | 修改级别 | 说明 | +|------|---------|------| +| `main.py` | ✏️ 修改 | 新增 `_find_balllist_template_path()` 函数;修改 `run_map_to_list()` 中的模板查找调用 | + +**不涉及**:`pinmap_parser.py`, `pinlist_generator.py`, `xlsx_writer.py`, `template_reader.py`(这些模块只接收 `TemplateStyle` 对象,不关心模板文件名) + +#### 3.2.3 具体修改方案 + +**3.2.3.1 新增 `_find_balllist_template_path()` 函数**: + +```python +def _find_balllist_template_path() -> str | None: + """查找根目录下的 BallList-Template.xlsx。 + + 搜索顺序: + 1. 与 run.bat 同级的根目录 + 2. 当前工作目录 + """ + src_dir = os.path.dirname(os.path.abspath(__file__)) + root_dir = os.path.dirname(os.path.dirname(src_dir)) # pinmap-to-pinlist/ + template_path = os.path.join(root_dir, "BallList-Template.xlsx") + + if os.path.exists(template_path): + return template_path + + cwd_template = os.path.join(os.getcwd(), "BallList-Template.xlsx") + if os.path.exists(cwd_template): + return cwd_template + + return None +``` + +**3.2.3.2 修改 `run_map_to_list()` 中的模板查找**: + +```python +# 修改前: +template_path = _find_template_path() +template_style = None +if template_path: + template_style = read_template_styles(template_path) + +# 修改后: +template_path = _find_balllist_template_path() +template_style = None +if template_path: + template_style = read_template_styles(template_path) + if template_style: + print(f"[INFO] 已加载 BallList 模板样式: {template_path}") + else: + print("[WARN] BallList 模板文件存在但解析失败,使用默认样式") +else: + print("[INFO] 未检测到 BallList-Template.xlsx,使用默认样式") +``` + +**3.2.3.3 输出路径保持不变**: + +PinList 输出路径仍为 `{input_base}_PinList.xlsx`,不受模板变更影响。 + +#### 3.2.4 风险评估 + +| 风险 | 影响 | 概率 | 缓解措施 | +|------|------|------|---------| +| 用户未放置 BallList-Template.xlsx | 低 | 高 | 模板不存在 → 优雅降级使用默认样式(已实现) | +| 新旧模板共存产生混淆 | 低 | 低 | 日志明确输出使用的模板文件名 | +| BallList-Template.xlsx 解析失败 | 低 | 低 | template_reader 已有 try-except 降级 | + +**工作量**:15 分钟 + +--- + +### 3.3 F010: List→MAP 使用 ballmap 模板 + +#### 3.3.1 需求 + +> PinList→PinMAP 转换方向查找并使用 `BallMAP-Template.xlsx`,不再共用 PinMAP 模板 + +**变更前**:`run_list_to_map()` 使用 `_find_template_path()` → `PinMAP-Template.xlsx` +**变更后**:`run_list_to_map()` 查找并使用 `BallMAP-Template.xlsx` + +#### 3.3.2 影响范围 + +仅在 `main.py` 中修改模板查找逻辑。 + +**涉及文件**: + +| 文件 | 修改级别 | 说明 | +|------|---------|------| +| `main.py` | ✏️ 修改 | 新增 `_find_ballmap_template_path()` 函数;修改 `run_list_to_map()` 中的模板查找调用 | + +#### 3.3.3 具体修改方案 + +**3.3.3.1 新增 `_find_ballmap_template_path()` 函数**: + +```python +def _find_ballmap_template_path() -> str | None: + """查找根目录下的 BallMAP-Template.xlsx。 + + 搜索顺序: + 1. 与 run.bat 同级的根目录 + 2. 当前工作目录 + """ + src_dir = os.path.dirname(os.path.abspath(__file__)) + root_dir = os.path.dirname(os.path.dirname(src_dir)) # pinmap-to-pinlist/ + template_path = os.path.join(root_dir, "BallMAP-Template.xlsx") + + if os.path.exists(template_path): + return template_path + + cwd_template = os.path.join(os.getcwd(), "BallMAP-Template.xlsx") + if os.path.exists(cwd_template): + return cwd_template + + return None +``` + +**3.3.3.2 修改 `run_list_to_map()` 中的模板查找**: + +```python +# 修改前: +template_path = _find_template_path() +template_style = None +if template_path: + template_style = read_template_styles(template_path) + ... + +# 修改后: +template_path = _find_ballmap_template_path() +template_style = None +if template_path: + template_style = read_template_styles(template_path) + if template_style: + print(f"[INFO] 已加载 BallMAP 模板样式: {template_path}") + else: + print("[WARN] BallMAP 模板文件存在但解析失败,使用默认样式") +else: + print("[INFO] 未检测到 BallMAP-Template.xlsx,使用默认样式") +``` + +#### 3.3.4 风险评估 + +| 风险 | 影响 | 概率 | 缓解措施 | +|------|------|------|---------| +| 用户未放置 BallMAP-Template.xlsx | 低 | 高 | 优雅降级使用默认样式 | +| 新旧模板共存产生混淆 | 低 | 低 | 日志明确输出使用的模板文件名 | + +**工作量**:15 分钟 + +--- + +### 3.4 F011: 模板格式提取式应用 + +#### 3.4.1 需求 + +> 从模板仅提取格式信息(字体、边框、对齐、列宽、行高),输出文件行列数由实际 Pin 数量决定,不复制模板行列结构。 + +**依赖**:F009(BallList-Template.xlsx)+ F010(BallMAP-Template.xlsx) + +#### 3.4.2 当前实现分析 + +当前模板应用于 `StyledXLSXWriter`(`xlsx_writer.py`),其行为: + +**`_sheet_xml()` 中的列宽/行高处理**: +```python +# 当前逻辑: +# 1. 遍历模板 style.column_widths,按最大 col 扩展 +# 2. 对于模板有定义的列使用模板宽度,否则默认 8.0 +# 3. 遍历 style.row_heights,有定义的行使用模板行高 +col_widths_xml = '' +if self._style and self._style.column_widths: + max_width_col = max(self._style.column_widths.keys()) + max_width_col = max(max_width_col, max_col) + for c in range(max_width_col + 1): + width = self._style.column_widths.get(c, 8.0) + ... +``` + +**`_styles_xml()` 中的样式处理**: +```python +# 当前逻辑:硬编码 4 种 xf 样式 +# - xf 0: default +# - xf 1: centered + thin border(pin cells) +# - xf 2: bold + centered(A1) +# - xf 3: centered + border + light fill(header) +# +# 仅从模板提取: +# - font[0] 的 name/size/color(用于 xf 0, 1, 3) +# - font[0] 被复制为 font[1](bold 版,用于 xf 2 = A1) +``` + +#### 3.4.3 关键分析:当前实现是否已满足 F011 要求 + +| F011 要求 | 当前实现 | 是否满足 | +|-----------|---------|---------| +| 仅提取格式信息 | ✅ 模板仅用于样式 | ✅ 已满足 | +| 字体 | ✅ 从模板 font[0] 提取 | ✅ 已满足 | +| 边框 | ❌ 硬编码 thin border | ⚠️ 部分满足 | +| 对齐 | ✅ 硬编码 center/center | ⚠️ 部分满足 | +| 列宽 | ✅ 从模板提取 | ✅ 已满足 | +| 行高 | ✅ 从模板提取(有则不覆盖) | ✅ 已满足 | +| 输出行列由实际 Pin 决定 | ✅ 不复制模板行列结构 | ✅ 已满足 | +| 不复制模板行列结构 | ✅ dim 由数据决定 | ✅ 已满足 | + +**核心差距**:当前 `_styles_xml()` 中边框和对齐是硬编码的,未从模板的 `cellXfs` 中提取。F011 要求**完全**从模板提取格式。 + +#### 3.4.4 修改方案 + +**目标**:将 `_styles_xml()` 改造为从模板的 `cellXfs`、`fonts`、`borders`、`fills` 中提取并原样输出样式,而非硬编码。 + +**涉及文件**: + +| 文件 | 修改级别 | 说明 | +|------|---------|------| +| `template_reader.py` | ✏️ 修改 | 增强样式提取能力:提取 cellXfs 的完整信息(含 numFmtId, xfId 等) | +| `xlsx_writer.py` | ✏️ 修改 | 重写 `_styles_xml()` 使用模板原始样式定义 | + +**3.4.4.1 增强 `template_reader.py`**: + +当前 `TemplateReader._parse_styles_xml()` 已能提取: +- ✅ fonts(FontStyle: name, size, bold, italic, color) +- ✅ fills(FillStyle: pattern_type, fg_color) +- ✅ borders(BorderStyle: top, bottom, left, right, color) +- ✅ cell_xfs(list[dict]: numFmtId, fontId, fillId, borderId, alignment) + +**需要增加**: +- `cell_xfs` 中的 `xfId` 属性(用于样式继承) +- `cellXfs` 的 `count` 属性 + +当前已提取的信息足以满足 F011。**不需要大幅修改** `template_reader.py`。 + +**3.4.4.2 重写 `xlsx_writer.py` 中的 `_styles_xml()`**: + +```python +def _styles_xml(self) -> str: + """Build xl/styles.xml from template styles or defaults.""" + s = self._style + + # ── Fonts ──────────────────────────────────────────────── + if s and s.fonts: + fonts_xml = self._build_fonts_xml(s.fonts) + else: + fonts_xml = self._default_fonts_xml() + + # ── Fills ──────────────────────────────────────────────── + if s and s.fills: + fills_xml = self._build_fills_xml(s.fills) + else: + fills_xml = self._default_fills_xml() + + # ── Borders ────────────────────────────────────────────── + if s and s.borders: + borders_xml = self._build_borders_xml(s.borders) + else: + borders_xml = self._default_borders_xml() + + # ── Cell XFs ───────────────────────────────────────────── + if s and s.cell_xfs: + cell_xfs_xml = self._build_cell_xfs_xml(s.cell_xfs) + else: + cell_xfs_xml = self._default_cell_xfs_xml() + + return ( + '\n' + '\n' + + fonts_xml + '\n' + + fills_xml + '\n' + + borders_xml + '\n' + + cell_xfs_xml + '\n' + + '' + ) +``` + +**关键设计决策**: + +| 决策点 | 方案 | 理由 | +|--------|------|------| +| 是否完全复制模板 cellXfs | ✅ 是 | 模板定义什么样式就用什么样式 | +| 是否需要额外样式(如 A1 bold) | ⚠️ 在模板中应有对应的 xf | 鼓励用户在模板中定义 A1 的样式 | +| 无模板时的默认样式 | 保持现有硬编码 | 向后兼容 | +| 列宽/行高处理 | 保持现有逻辑 | 已满足 F011 | + +**3.4.4.3 cellXfs 映射策略**: + +模板的 cellXfs 索引需要映射到输出单元格: +- 模板中可能有多种 xf(如 xf 0=default, xf 1=边框, xf 2=粗体...) +- 输出时需决定每个单元格使用哪个 xf + +**推荐策略**: +1. 分析模板 cellXfs,找到最合适的 "pin cell" 样式(通常是带边框+居中的 xf) +2. A1 使用模板中带 bold 的 xf(如果存在),否则用 pin cell 样式 +3. 普通 pin cell 使用模板中的 "pin cell" xf +4. 如果模板只有 1 个 xf(default),使用默认样式作为补充 + +**简化方案**(推荐首版): +- 保留现有的 4 个样式槽位(xf 0~3) +- 但从模板读取实际的字体、边框、填充定义填充到对应槽位 +- 而非硬编码 "thin" 边框和 "center" 对齐 + +**实现优先级**: +1. **字体信息**:已从模板读取 ✅ +2. **边框样式**:从模板 borders 读取 → 替换硬编码的 "thin" +3. **填充样式**:从模板 fills 读取 → 替换硬编码的 "FFF0F0F0" +4. **对齐方式**:从模板 alignment 读取 → 替换硬编码的 "center" +5. **列宽/行高**:已从模板读取 ✅ + +#### 3.4.5 风险评估 + +| 风险 | 影响 | 概率 | 缓解措施 | +|------|------|------|---------| +| 模板 cellXfs 结构与输出不匹配 | 中 | 中 | 提供合理的 fallback(至少 xf 0 和 xf 1) | +| 模板无边框定义导致输出无网格线 | 中 | 低 | 模板无边框时保留默认 thin border | +| 样式重写引入 OOXML 兼容性问题 | 低 | 低 | 使用 Python 标准库 XML 构建,避免硬编码 namespace 错误 | +| 已有用户无模板场景不受影响 | 低 | - | 无模板时完全回退到现有硬编码样式 | + +**工作量**:2–3 小时 + +--- + +## 4. 模板文件命名规范建议 + +### 4.1 v1.5.0 新模板命名 + +| 用途 | 文件名 | 位置 | 格式 | +|------|--------|------|------| +| MAP→List 输出样式 | `BallList-Template.xlsx` | 项目根目录(与 run.bat 同级) | `.xlsx` | +| List→MAP 输出样式 | `BallMAP-Template.xlsx` | 项目根目录(与 run.bat 同级) | `.xlsx` | + +### 4.2 向后兼容 + +| 旧文件名 | 状态 | 说明 | +|---------|------|------| +| `PinMAP-Template.xlsx` | ⚠️ 废弃(不再自动查找) | v1.5.0 后不再被代码引用 | + +### 4.3 命名规范说明 + +``` +模板文件名格式: + {输出格式简称}-Template.xlsx + + 其中: + - BallList → PinMAP→PinList 转换的输出格式(PinList) + - BallMAP → PinList→PinMAP 转换的输出格式(PinMAP) + +命名原则: + 1. 以输出格式命名,而非输入格式 + 2. 使用 "Ball" 前缀避免与 "Pin" 名混淆 + 3. 保持 PascalCase 风格 + 4. 使用 "-Template" 后缀明确表示模板文件 +``` + +### 4.4 搜索路径优先级 + +``` +1. {project_root}/BallList-Template.xlsx (与 run.bat 同级) +2. {cwd}/BallList-Template.xlsx (当前工作目录) +3. 无 → 使用默认样式(硬编码 Calibri 11pt + thin border + center align) +``` + +--- + +## 5. 修改影响矩阵 + +| 文件 | F012 | F009 | F010 | F011 | 总改动量 | 备注 | +|------|------|------|------|------|---------|------| +| `main.py` | — | ✏️ 模板查找 | ✏️ 模板查找 | — | ~30行 | 新增2个函数+修改2处调用 | +| `pinmap_layout.py` | ✏️ 可能 | — | — | — | ~5行 | 仅在确认问题后修改 | +| `template_reader.py` | — | — | — | ✏️ 增强 | ~20行 | 增加 xfId 提取 | +| `xlsx_writer.py` | — | — | — | ✏️ 重写 | ~100行 | 重写 _styles_xml() | +| `test_pinmap.py` | ✏️ 更新 | — | — | — | ~10行 | 增加 F012 回归测试 | +| **合计** | **2 文件** | **1 文件** | **1 文件** | **2 文件** | **4-5 文件** | | + +--- + +## 6. 优先级排序 + +| 优先级 | 编号 | 原因 | 推荐执行顺序 | +|--------|------|------|------------| +| **P0** | F012 | 核心布局 Bug(需先确认),影响所有 List→MAP 转换 | 第1(先确认,再决定是否修改) | +| **P1-1** | F009 | MAP→List 模板分离,独立于其他改动 | 第2(可与 F010 并行) | +| **P1-2** | F010 | List→MAP 模板分离,独立于其他改动 | 第2(可与 F009 并行) | +| **P1-3** | F011 | 依赖 F009+F010 的模板文件存在后才能测试 | 第3 | + +--- + +## 7. 测试要点 + +### 7.1 F012 测试(P0) + +#### 核心验证 + +| 测试项 | 输入 | 预期 | 方法 | +|--------|------|------|------| +| 4×4 PinMAP 往返一致性 | PinList(rows=4, cols=4, 8 Pins) → PinMAP → PinList | 往返后 PinList 数据不变 | 自动化 | +| 下边 Name 位置 | rows=4, cols=4 的 PinMAP 输出 | 下边 PinName 在序号行上方一行(max_row-1) | 检查输出 xlsx | +| 上边 Name 位置 | rows=4, cols=4 的 PinMAP 输出 | 上边 PinName 在序号行下方一行(min_row+1) | 检查输出 xlsx | +| 与 parser 一致性 | 生成的 PinMAP 再用 parser 解析 | 解析出的 Pin 数据和原始一致 | 自动化 | +| 非方形网格 | rows=3, cols=5 的 PinMAP | 上/下边 Name 位置正确 | 检查输出 | + +#### 边界条件 + +| 测试项 | 输入 | 预期 | +|--------|------|------| +| 最小网格 2×2 | PinList(rows=2, cols=2, 8 Pins) | 四条边各 2 Pin,角点正确 | +| 大网格 15×15 | PinList(rows=15, cols=15, 60 Pins) | 60 Pin 全部正确分配到四条边 | +| max_row-1 与 min_row+1 重合 | rows=2(min_row=1, max_row=2 → max_row-1=1=min_row) | Name 不与序号重叠 | + +#### 现有测试回归 + +- `test_4x4_parse()` — 确认不受影响或同步更新 +- `test_4x4_validate()` — 确认不受影响 +- `test_12pin_square()` — 确认不受影响 + +### 7.2 F009 测试(P1) + +| 测试项 | 方法 | 预期 | +|--------|------|------| +| BallList-Template.xlsx 存在时加载 | 放置模板 → MAP→List 转换 | 日志显示"已加载 BallList 模板样式" | +| BallList-Template.xlsx 不存在时降级 | 删除模板 → MAP→List 转换 | 日志显示"未检测到 BallList-Template.xlsx",输出使用默认样式 | +| 不加载 PinMAP-Template.xlsx | 仅放置 PinMAP-Template.xlsx → MAP→List 转换 | 不加载旧模板,使用默认样式 | +| 模板样式应用到 PinList 输出 | 放置带自定义字体/边框的模板 → 转换 | 输出 PinList 使用模板字体和边框 | + +### 7.3 F010 测试(P1) + +| 测试项 | 方法 | 预期 | +|--------|------|------| +| BallMAP-Template.xlsx 存在时加载 | 放置模板 → List→MAP 转换 | 日志显示"已加载 BallMAP 模板样式" | +| BallMAP-Template.xlsx 不存在时降级 | 删除模板 → List→MAP 转换 | 日志显示"未检测到 BallMAP-Template.xlsx",输出使用默认样式 | +| 不加载 PinMAP-Template.xlsx | 仅放置 PinMAP-Template.xlsx → List→MAP 转换 | 不加载旧模板,使用默认样式 | + +### 7.4 F011 测试(P1) + +| 测试项 | 方法 | 预期 | +|--------|------|------| +| 模板字体正确应用 | 模板字体=微软雅黑 12pt → 输出 | 输出文件字体为微软雅黑 12pt | +| 模板边框正确应用 | 模板边框=medium → 输出 | 输出文件边框为 medium 而非 thin | +| 模板填充正确应用 | 模板背景色=黄色 → 输出 | 输出对应单元格有黄色背景 | +| 模板对齐正确应用 | 模板左对齐 → 输出 | 输出文件单元格左对齐 | +| 列宽与模板一致 | 模板 A 列宽=20 → 输出 | 输出对应列宽=20 | +| 行高与模板一致 | 模板行高=25 → 输出 | 输出对应行高=25 | +| 输出行列由实际 Pin 决定 | rows=5, cols=5 → 输出 | 输出为 5×5 网格,不含模板的额外行列 | +| 无模板时使用默认样式 | 无模板文件 → 输出 | 使用 Calibri 11pt + thin border + center align | + +### 7.5 集成测试 + +| 测试项 | 输入 | 预期 | +|--------|------|------| +| 往返转换 (MAP→List→MAP) | sample_4x4.xlsx → PinList → PinMAP | 与原始 PinMAP 一致 | +| 往返转换 (List→MAP→List) | PinList 文件 → PinMAP → PinList | 与原始 PinList 一致 | +| 两个方向使用不同模板 | BallList-Template 和 BallMAP-Template 同时存在 | MAP→List 用 BallList,List→MAP 用 BallMAP | +| 一个大模板一个小模板 | BallList 字体=12pt, BallMAP 字体=10pt | 各方向使用各自的字体 | + +--- + +## 8. 开发顺序建议 + +``` +阶段 1: F012 需求确认(30 分钟) + ├─ 用实际 PinMAP 输入文件测试当前代码的 PinName 位置 + ├─ 确认 Bug 具体表现 + └─ 决定修改方案(A/B/C) + +阶段 2: F009 + F010 模板分离(30 分钟,可并行) + ├─ main.py: 新增 _find_balllist_template_path() + ├─ main.py: 新增 _find_ballmap_template_path() + ├─ main.py: 修改 run_map_to_list() 模板查找 + ├─ main.py: 修改 run_list_to_map() 模板查找 + └─ 废弃 _find_template_path()(可选,保留无调用不影响) + +阶段 3: F012 修复(如需要,30–60 分钟) + ├─ pinmap_layout.py: 修改 get_name_cell() + ├─ test_pinmap.py: 更新测试数据和断言 + └─ 运行完整测试套件 + +阶段 4: F011 格式提取(2–3 小时) + ├─ template_reader.py: 增加提取项 + ├─ xlsx_writer.py: 重写 _styles_xml() + ├─ xlsx_writer.py: 新增 _build_*_xml() 辅助函数 + └─ 模板+无模板场景测试 + +阶段 5: 收尾(30 分钟) + ├─ 更新 CHANGELOG.md + ├─ 更新 features.md 状态 + ├─ 更新 VERSION 文件 + └─ 运行完整回归测试 +``` + +--- + +## 9. 风险评估汇总 + +| 风险 | 影响 | 概率 | 缓解措施 | 相关功能 | +|------|------|------|---------|---------| +| F012 需求描述与代码行为不一致,修改方向错误 | **高** | 中 | **先确认再改**,使用实际文件测试 | F012 | +| F012 修改破坏往返转换一致性 | **高** | 中 | 运行完整 MAP→List→MAP 往返测试 | F012 | +| 模板 cellXfs 结构与输出不兼容 | 中 | 中 | 提供 fallback,模板解析失败 = 默认样式 | F011 | +| 用户未放置新模板文件 | 低 | 高 | 优雅降级,日志明确提示缺失的模板名 | F009/F010 | +| 旧 PinMAP-Template.xlsx 被意外加载 | 低 | 低 | 显式删除旧模板查找调用 | F009/F010 | +| F011 样式重写引入 OOXML 兼容性问题 | 低 | 低 | 严格 XML 构建,测试 Excel/WPS 打开 | F011 | +| 两个模板同时存在造成混淆 | 低 | 低 | 日志明确标注每个方向使用的模板文件名 | F009/F010 | + +--- + +## 10. 工作量估算 + +| 阶段 | 任务 | 预估时间 | 依赖 | +|------|------|---------|------| +| 确认 | F012 需求确认(测试+分析) | 30 分钟 | 无 | +| 开发 | F009 MAP→List 模板分离 | 15 分钟 | 无 | +| 开发 | F010 List→MAP 模板分离 | 15 分钟 | 无 | +| 开发 | F012 修复(如需要) | 30–60 分钟 | 需求确认 | +| 开发 | F011 模板格式提取式应用 | 2–3 小时 | F009+F010 | +| 测试 | 单元测试更新 | 30 分钟 | 所有开发 | +| 测试 | 集成/回归测试 | 30 分钟 | 所有开发 | +| 文档 | CHANGELOG + features.md 更新 | 15 分钟 | 所有开发 | +| **总计** | | **4.5–6 小时** | | + +--- + +## 11. 总结 + +| 项目 | 内容 | +|------|------| +| 修改文件数 | 4–5 个(main.py, pinmap_layout.py, template_reader.py, xlsx_writer.py, test_pinmap.py) | +| 新增模板文件 | 2 个(BallList-Template.xlsx, BallMAP-Template.xlsx) | +| 影响核心模块 | 是(xlsx_writer.py 样式生成逻辑重写) | +| 技术难度 | 中(F011 样式重写需理解 OOXML styles.xml 结构) | +| 预估工作量 | 4.5–6 小时 | +| 推荐 Agent | Python 编码 Agent | +| 风险等级 | 中(F012 需先确认,F011 样式重写有复杂度) | + +**关键结论**: + +1. **F012(P0)**:代码当前行为可能已经正确(bottom Name 在 max_row-1,top Name 在 min_row+1 已与 F012 "应改为"目标一致)。**强烈建议在实施前用实际文件验证**,避免过度修改。如果确认无误,仅需增加回归测试。 + +2. **F009+F010(P1)**:改动量小(约 30 行),完全独立,可快速完成。核心是新增两个模板查找函数并替换调用点。 + +3. **F011(P1)**:改动量最大(约 120 行),需重写 `xlsx_writer.py` 的 `_styles_xml()` 方法。当前代码已部分满足 F011(字体、列宽、行高从模板提取),主要差距在边框和对齐的硬编码。建议采用"从模板读取实际值填充现有样式槽位"的渐进方案。 + +4. **向后兼容**:无模板时所有功能完全回退到现有默认样式,不影响已有用户。 + +5. **推荐开发顺序**:确认 F012 → 实现 F009+F010 → 修复 F012(如需要) → 实现 F011 → 测试收尾。 + +--- + +*文档结束 — 请审批后进入编码阶段* + +## \ No newline at end of file diff --git a/docs/tasks.md b/docs/tasks.md index aff6a6b..cc2d003 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -14,6 +14,7 @@ | T013 | 打包发布 v1.3.15 修复 | package-release-agent | 已完成 | 打包发布 | - | 2026-06-02 | 2026-06-02 | Release 已创建 + zip 附件已上传 | | T014 | 架构评估 v1.5 | script-architect | 已完成 | 架构评估 | F009-F012 | 2026-06-06 | 2026-06-06 | | T015 | 编码实现 v1.5 | python-coding-agent | 已完成 | 编码实现 | F009-F012 | 2026-06-06 | 2026-06-06 | -| T016 | 测试验证 v1.5 | test-architect/test-executor/test-reporter | 待处理 | 测试验证 | F009-F012 | - | - | -| T017 | 文档生成 v1.5 | doc-gen-agent | 待处理 | 文档编写 | F009-F012 | - | - | +| T016 | 测试验证 v1.5 | test-architect/test-executor/test-reporter | 已完成 | 测试验证 | F009-F012 | 2026-06-06 | 2026-06-06 | +| T017 | 文档生成 v1.5 | doc-gen-agent | 已完成 | 文档编写 | F009-F012 | 2026-06-06 | 2026-06-06 | +| T018 | 打包发布 v1.5 | package-release-agent | 进行中 | 打包发布 | F009-F012 | 2026-06-06 | - | | T018 | 打包发布 v1.5 | package-release-agent | 待处理 | 打包发布 | F009-F012 | - | - |