文本与调试

正则、Diff 与文本调试:用最小样例构建证据

只有明确算法与局限,文本工具才真正有用。本指南区分匹配证据、位置变化、格式化与真正语法验证。

在不改变问题的前提下缩减失败

从已授权且不敏感的输入开始,逐项删除无关行、字段和值。保留一个正例、一个近似但不匹配的样例和一个明确反例。实用最小样例会保留影响行为的 Unicode、换行、空白和分隔符,同时删除凭据、个人数据和生产标识。

运行工具前先写下预期观察。对于正则,说明完整匹配和捕获组;对于 Diff,说明顺序与空白是否有意义;对于 SQL,说明目标是可读性、语法有效、结果等价还是执行计划。这些是不同测试,需要不同权威工具。

测试准确的正则引擎

正则语法和行为在 JavaScript、PCRE、RE2、.NET、Java 和数据库引擎之间不同。标志、Unicode 属性、后行断言、命名组、锚点和替换转义都可能变化。浏览器测试器只能确定当前浏览器的 JavaScript 行为;接受表达式前应把样例转到生产语言。

加入空输入、多行输入、非 ASCII 文本和很长的对抗性近似匹配。回溯表达式在普通样例上可能很快,却在特制失败输入上意外昂贵。当不可信用户能影响模式或样例时,应设置输入限制和执行控制;威胁模型需要时优先选择线性时间引擎。

正确解释位置逐行 Diff

位置比较器把第一行与第一行、第二行与第二行依次并排,适合小型固定布局配置快照。它不是序列对齐算法:插入一行会移动之后每一对并产生大量表面变化。新增和删除属于常态时,应改用版本控制 Diff。

结构化格式应使用结构化比较。把 JSON、YAML、XML 或配置解析为模型,只规范化文档明确无关的属性,再比较语义值。除非格式说明顺序或空白无关,否则不要排序数组或裁剪空白。清晰的语义 Diff 应保留回到原始源行的路径以便复核。

区分 SQL 格式化与数据库验证

轻量 SQL 格式化器可以显示简单语句中的 FROM、WHERE、JOIN 和排序子句。基于关键字替换空白并不能理解注释、带引号标识符、美元引号字符串、过程块或所有方言操作符。不要仅因格式更整洁就假设重排语句保持语义。

使用目标数据库解析器验证语法,并通过非生产事务或仅 Explain 功能验证行为。参数值应放在绑定参数中,而不是字符串拼接。修改生产查询时应比较返回行、类型、排序和执行计划,并保留原语句供复核。

把观察转化为回归测试

把最小输入、预期输出、运行时版本和断言原因保存在一起。增加因预期原因失败的反例,以及一个能发现原始缺陷的边界样例。截图或复制输出只是辅助证据,目标运行时中的可执行测试才是持久结果。

  • 每个语法测试都说明引擎和版本。
  • 结构化数据使用语义解析器。
  • 在目标解析器验证前,把格式化只视为展示。