对CAD库进行基线测试
摘要
作者描述了如何使用SVG输出和tasty-golden库为Waterfall-CAD Haskell库实现基线/视觉回归测试。
暂无内容
查看缓存全文
缓存时间: 2026/05/14 06:21
# 黄金测试一个CAD库
来源:https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html
正如我之前在这几篇文章中(https://doscienceto.it/blog/posts/2024-01-23-ffi.markdown)(https://doscienceto.it/blog/posts/2024-06-30-things-ive-3d-printed-in-haskell.md)(https://doscienceto.it/blog/posts/2024-09-15-chess-set.markdown)(https://doscienceto.it/blog/posts/2025-04-14-waterfall-cad-svg.md)所写到的,我是Haskell可编程CAD库Waterfall-CAD(https://hackage.haskell.org/package/waterfall-cad)的作者/维护者。
自从2023年发布这个库以来,我一直因为没有测试而困扰。
测试像Waterfall-CAD这样的CAD库很困难,因为Waterfall-CAD程序的输出通常是3D模型,很难编写好的测试断言。
2025年,我为Waterfall-CAD添加了SVG支持(https://hackage.haskell.org/package/waterfall-cad-svg),将README.md(https://github.com/joe-warren/opencascade-hs#examples)中的图片从网格查看器的截图转换为直接在Haskell代码中生成的矢量图。
虽然测试实体模型看起来本质上很棘手,但存在一个成熟的“视觉回归测试”工具领域,因此使用SVG输出似乎比3D模型输出更易于测试¹(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#fn1)。
## 视觉回归测试(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#visual-regression-testing)
“视觉回归测试”主要用于测试UI代码。
“视觉回归工具”的工作原理是:存储应用程序生成的图像快照²(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#fn2),生成当前行为与该快照的视觉差异,如果当前行为看起来明显不同,则测试失败。它们通常还提供一种“接受”当前行为的机制——用新输出覆盖快照,以及一种可视化预期行为与实际行为差异的机制,突出显示快照中发生变化的部分。
### 术语说明(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#a-note-on-terminology)
“黄金测试”³(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#fn3)是一种测试技术的名称,其中程序的预期输出存储在一个文件中,通过将当前输出与该文件进行比较来测试程序。“黄金测试”工具通常也提供一种“接受”当前程序行为的机制,并用当前行为“覆盖”文件。
对我来说,将“视觉回归测试”视为“黄金测试”的一个特例似乎很有用,其中测试文件是图像,“差异”是视觉差异,而不是对文件二进制结构的精确比较。
在开始这个项目时,我认为我想要编写的测试类型叫做“快照测试”。
现在我很确定这是不正确的,“快照测试”似乎用于描述与“黄金测试”完全相同的技术(尽管不同的术语在不同编程语言社区中很常见)。
我目前用“视觉回归测试”来描述我正在做的事情;我认为这与(同样常用的)术语“视觉快照测试”是同义词。
我仍然认为将其视为“黄金测试”或“快照测试”的一个特例是有用的。实际上,我正使用Haskell的黄金测试库tasty-golden(https://hackage.haskell.org/package/tasty-golden)⁴(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#fn4)来实现这些测试。
## 我具体在做什么(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#what-im-doing-specificly)
我添加了一系列基于已经为README生成的图表的测试。
这些图像以SVG格式存储,并包含一些自定义CSS(https://github.com/joe-warren/opencascade-hs/blob/f88a23e3d7196778e118a4c0916fedcd0c9b54fa/waterfall-cad-examples/src/DarkModeSVG.hs),因此它们会根据README是否处于暗色模式而呈现不同的效果。
我喜欢让图像具有双重用途,因为这样可以减少需要同步的工作量。
使用Rasterific-SVG(https://hackage.haskell.org/package/rasterific-svg)库,将仓库中的SVG和被测代码生成的SVG都转换为JuicyPixels图像(https://hackage.haskell.org/package/JuicyPixels-3.3.9/docs/Codec-Picture.html#t:Image)。
有了两张图像后,代码断言它们具有相同的大小。如果大小相同,则比较每个像素,并计算曼哈顿距离(https://en.wikipedia.org/wiki/Taxicab_geometry)超过一定阈值的像素数量。如果这个不匹配像素数量高于某个容差值,测试失败。
测试失败时,会写入一张“差异图像”,突出显示发生差异的像素。
你可以在GitHub仓库的`DiagramGoldenTests.hs`文件(https://github.com/joe-warren/opencascade-hs/blob/eebecad0ec7cee184bdd03f0f2fe7dbe19145024/waterfall-cad-examples/test/DiagramGoldenTests.hs#L4)中看到执行所有这些操作的代码。
我故意通过更改隐藏线使用的颜色来让测试失败,从而生成这张图像。
## 这里面有开源库吗?(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#is-there-an-open-source-library-in-this)
我认为*可能*有。
但目前,我离把它写出来还差一小步。
一个合适的库需要支持更多JuicyPixels的像素格式(https://hackage.haskell.org/package/JuicyPixels-3.3.9/docs/Codec-Picture.html#i:Pixel)。
它需要使差异可视化更加可定制(如果图像已经包含大量红色,你肯定不想用红色来显示差异)。
它还需要支持直接从磁盘加载图像,而不是像我这样进行“通过SVG转换”的杂耍。
目前,我倾向于*不进行这些改进*,但我很纠结,如果有一个人说“是的,我会用这个”,我很有可能被说服。
---
¹ 就像“知道应该吃蔬菜”一样,渴望编写测试比实际编写它们容易得多,因此从添加SVG支持到进行测试之间间隔了近一年。↩︎(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#fnref1)
² 在测试用户界面时,通常是应用程序的屏幕截图;不过在这个特定案例中不是。↩︎(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#fnref2)
³ 或者“特性测试”(https://en.wikipedia.org/wiki/Characterization_test),或者“黄金记录测试”,或者“黄金主测试”↩︎(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#fnref3)
⁴ `tasty-silver`(https://hackage.haskell.org/package/tasty-silver)是`tasty-golden`一个相对常用的分支;我认为这也值得一提。↩︎(https://doscienceto.it/blog/posts/2026-04-27-golden-testing-cad.html#fnref4)
相似文章
Waterfall CAD Playground - 一个由 Haskell 驱动的可编程 CAD 环境,通过 WASM 在浏览器中运行
一个基于浏览器的 Haskell 驱动的可编程 CAD 环境,通过 WebAssembly 运行,需要下载较大的 WASM blob。
展示HN:LuaCAD – 使用Lua脚本化参数CAD
LuaCAD是一个可脚本化的CAD工具,使用Lua进行参数化2D和3D建模,基于Rust引擎构建,支持多种导出格式和CSG操作。
面向LLM驱动HDL设计与验证数据策展的结构化测试台生成
本文提出STG,一种用于LLM驱动硬件设计工作流的结构化测试台生成框架,与现有基于提示的方法相比,它降低了token成本并提高了验证可靠性。
基于有限元分析反馈的自我改进CAD生成代理
本文提出了一种新的CAD生成任务形式,将有限元分析作为反馈,并结合了改进的监督信号,如纯文本蓝图方案和多视角图像渲染器,从而在基准测试中实现了更好的几何重建。
CADAM
CADAM 是一个类似于 Tinkercad 的 AI 驱动 CAD 工具,已在 Product Hunt 上发布。