Harper 语料库快照测试体系:以 `tests/text/Computer science.md` 维基百科语料为例
2026/9/14 16:19:35 网站建设 项目流程

Harper 语料库快照测试体系:以tests/text/Computer science.md维基百科语料为例

【免费下载链接】harperOffline, privacy-first grammar checker. Fast, open-source, Rust-powered项目地址: https://gitcode.com/GitHub_Trending/har/harper

Harper 的harper-core/tests/text/目录存放着一批真实英文语料,其中 Computer science.md 是一份节选自维基百科的计算机科学条目(508 行,约 1.3 万字符)。这篇文章以它为主体,讲清它在 Harper 测试体系中的真实身份——不是文档,而是一份驱动「词性标注快照」与「Lint 结果快照」两套回归测试的黄金语料——并基于该语料对应的两份快照产物(1064 行的 POS 标注文件与 1358 行的 Lint 报告文件),完整还原 Harper 如何对一段 500 行 Markdown 做分词、标注、拼写、风格与可读性检查,以及 CI 如何用快照不一致来拦截回归。

一、语料文件本体:来源、许可与被遮蔽的头部注释

先看语料本身的结构。Computer science.md 的前 4 行是一个 HTML 注释,声明了出处与许可证:

<!-- source: https://en.wikipedia.org/w/index.php?title=Computer_science&oldid=1286173304 license: CC BY-SA 4.0 -->

随后是一级标题# Computer science与正文,覆盖 History、Etymology and scope、Philosophy(含 Epistemology、Paradigms 两节)、Fields(理论计算机科学、应用计算机科学、计算机系统等三级小节)、Discoveries、Programming paradigms、Research 等完整章节。选维基百科条目做语料是有意为之:文本中密集出现历史人名地名(Wilhelm Schickard、Gottfried Leibniz、Ada Lovelace、Thomas de Colmar、Percy Ludgate、Leonardo Torres Quevedo)、专业术语(arithmometer、Stepped Reckoner、Analytical Engine)、引号与脚注标记([note 1])、长句与多范式例句,几乎能同时压测 Harper 的拼写检查器、大小写检查器、标点风格检查器和长句可读性检查器。

一个容易被忽略的细节:头部那段 HTML 注释在标注快照中被整体打上了Unlintable标记(见 tagged/Computer science.md 第 1–8 行,Unlintable连续出现在source:license:各行上方)。也就是说 Harper 的词法层会把该注释识别为一种不可 lint 的 token,许可声明不会进入拼写/风格检查,这避免了w/index.phpCC BY-SA这类内容产生噪声。

二、语料在测试流水线中的位置:tests/text是唯一的语料入口

Harper 并没有为这份语料手写断言,而是通过一套「目录扫描 + 快照比对」机制自动消费它。核心调度逻辑在 snapshot.rs:

  • get_text_dir()固定指向harper-core/tests/textget_text_files()遍历该目录,只收集扩展名为txtmd顶层文件——Computer science.md正被此规则命中;
  • snapshot_all_text_files(out_dir, ext, create_snapshot)用 rayon 的par_iter()并行处理每个文件:先调用回调生成快照内容,再与tests/text/<out_dir>/<文件名>中已有的快照逐字节比对。一致则通过;不一致则覆写快照文件并返回错误,最终panic!汇总所有失败文件(snapshot.rs 的tag_file函数)。

这个「失败即重写」的设计有两个后果:开发者本地跑一次测试就能看到最新行为并人工确认快照 diff;而在 CI 中由于不允许提交漂移,任何改变标注或 lint 行为的改动都会直接让测试红掉——linters.rs 与 pos_tags.rs 的模块文档都明确写了「This test will fail if the snapshot files are not up to date」,这是有意设置的回归闸门。

两条快照生产线分别由两个测试目标驱动:

测试目标入口函数消费语料方式快照输出目录快照扩展名
pos_tagstest_pos_tagger(pos_tags.rs)Document::new_markdown_default+fat_string_tokens()逐 token 输出词性标注tests/text/tagged.md
linterstest_most_lints(linters.rs)LintGroup::new_curated跑完整 lint 管线,按 span 排序后输出诊断tests/text/linters.snap.yml

因此Computer science.md这一个源文件,同时对应 tagged/Computer science.md(1064 行)与 linters/Computer science.snap.yml(1358 行)两份产物——前者记录「每个词被标成什么词性」,后者记录「每个 lint 规则在哪些行列触发、给出什么建议」。

三、POS 快照格式:逐词对齐的标注与本文档实例

pos_tags测试的快照格式在 pos_tags.rs 的模块文档中有完整定义:原文每个词性词对占两行,第一行以>开头放原文,第二行以#开头放标注,二者按字符数互相补空格对齐。以本文档第 13–14 行为例(摘自 tagged/Computer science.md):

> Computer science is the study of computation , information , and automation . # NSg+ N🅪Sg/VB+ VL3 D NSg/VB P NSg . Nᴹ+ .

is标为VL3(第三人称单数现在时系动词),study标为NSg/VB(单数名词或动词,斜杠表示 tagger 保留的不确定性),informationautomation标为Nᴹ+(不可数名词、且是名词短语成员)。标题Computer science则被标为NSg+ / N🅪Sg/VB+:前者是普通单数名词,后者中的🅪表示「既可按不可数、也可按可数处理」的名词用法,同时该词还能作动词(VB)。

标注体系本身由DictWordMetadata词元元数据推导(format_word_tag,pos_tags.rs),完整取值规则如下,这也是阅读任何tagged/快照的通用图例:

标注含义
N+Pr名词 / 专有名词
Sg/Pl单数 / 复数
Sg$/Pl$$后缀)属格(所有格)
(上标)不可数名词
🅪(上标)不可数且可数两可的名词
I+Sg/Pl/$代词,单数/复数/属格
V+L/X/B/P/Pr/Pt/Pp/3动词:系动词 / 助动词 / 原形(lemma)/ 过去时+过去分词合并 / 进行时 / 简单过去时 / 过去分词 / 第三人称单数
J+C/S形容词,比较级 / 最高级
R/C副词 / 连词
D+dem/q/$限定词:指示 / 量化 / 属格
P介词
AmBrCaAuNoAmComm方言标注(美式、英式、加式、澳式、北美区、英联邦区)
+名词短语成员
B粗口词(bad)
K/W?含撇号但字典未收录的缩合形 / 未收录词(无元数据则输出?
./#/#d/#r标点 / 数字 / 年代(decade)/ 罗马数字
SpaceNewlineParagraphBreakHeadingStartEmailUrlHostnameUnlintableRegexish其他 token 种类直接打印变体名

Computer science.md这份语料而言,标注快照同时暴露了若干值得注意的词法行为:HTML 注释整体成为Unlintable[note 1]这类脚注标记被逐词标注(NSg/VB+ # . NSg/VB+中的#即数字1);数字年份如16231673标为#。任何一次改动分词器、词典或元数据而导致的标注漂移,都会在这 1064 行里留下可逐行审查的 diff——这正是该快照的引用价值。

四、Lint 快照:这份语料实际触发了哪些检查

test_most_lints 先确定方言(默认Dialect::try_guess_from_document,猜不出则回退美式),再运行LintGroup::new_curated的完整 lint 组,把结果按span.startspan.end排序后写入快照。Computer science.snap.yml 中每条记录由三部分组成:Lint: <规则> (<优先级>)Message:代码块(带行号、^~~下划线与前后文)、Suggest:建议列表。从该快照可以确认这份语料至少触发了四类规则(规则名与优先级均直接摘自快照原文):

  1. Capitalization(优先级 127):首条 lint 就命中一级标题——# Computer science被提示「Try to use title case in headings.」,建议替换为# Computer Science(快照第 1–6 行)。
  2. Style(优先级 31):Oxford 逗号缺失——第 27 行planning and处提示「An Oxford comma is necessary here.」并给出Insert ","建议。
  3. Spelling(优先级 63):这是本语料产出 lint 最多的一类。语料中的历史人名与专业词大多不在策展词典中,于是产生了密集的真阴性对照,例如Schickard(建议 Schick's / Shipyard / Schick)、Gottfried(Guttered / Lotteries / Notified)、Reckoner(Reckoned / Rickover / Reasoner)、Colmar(Collar / Cellar / Clear)、arithmometer(arithmetic / anemometer,出现两次)、LudgateQuevedo等。这些条目恰好构成「拼写检查器面对罕见专有名词时的候选建议质量」的基准样本。
  4. Readability(优先级 127):长句检测。快照中至少标记了两处:第 59–62 行的句子被判定 48 词(「This sentence is 48 words long.」)、第 74–79 行 53 词;下划线~跨行延续表示 lint 的 span 跨越多行。

快照中Message的排版并非随意:linters.rs 的print_error会按字节偏移把 span 反解为行列,输出带行号({number:>6} | {line})的原文行、^~~定位线,并在命中位置离行首/行尾超过 40 列时自动补一行上文或下文。也就是说,快照不仅锁定「有哪些 lint」,还锁定「lint 的呈现方式」——连下划线渲染逻辑的改动都会触发回归。

五、方言约定与语料命名规则

同一目录下可以看到Spell.US.mdSpell.md这样的命名对。这不是随意取的:snapshot.rs 的try_get_dialect_override会从文件主名里解析方言缩写——按.切分后尝试Dialect::try_from_abbr,恰好解析出唯一一个时生效。于是Spell.US.md强制以美式英语方言跑 lint,而Computer science.md不含缩写后缀,走Dialect::try_guess_from_document的自动推断路径(推断失败回退美式)。该机制还有一条保护:若文件名能解析出多个方言缩写则视为非意图,忽略覆盖。

从语料组合看,tests/text/顶层共 11 份.md语料(Alice's Adventures in Wonderland、Difficult sentences、Part-of-speech tagging、Spell/Spell.US、Swear、The Constitution of the United States、The Great Gatsby、this and that 以及本文的 Computer science),加上 test_sources 中由 run_tests.rs 的create_test!宏逐一点名的回归用例(如create_test!(title_case_errors.md, 2, Dialect::American),断言精确的 lint 数量)。两类测试互补:run_tests管「特定 issue 的定点回归」,tests/text快照体系管「全量语料的行为基线」,Computer science.md属于后者中最重的一份通用英文长文基线。

六、运行方式与扩展该语料库的正确姿势

运行与本文相关的全部验证只需两条命令(在仓库根目录执行):

cargo test -p harper-core --test pos_tags cargo test -p harper-core --test linters

两个测试目标都会并行扫描tests/text下所有.md/.txt文件,Computer science.md及其两份快照会自然被包含在处理列表中(测试运行时会println!打印Processing ...逐文件进度)。

给语料库新增一份文档的流程由 pos_tags.rs 的文档直接写明:把文件放进tests/text,跑一次测试,快照即自动生成到tagged/linters/子目录;已有快照的更新同样是重跑测试。但要注意语义边界:本地「重跑即更新」是便利,CI 中「不一致即失败」才是约束。因此提交前必须人工核对快照 diff——如果 diff 里出现了你并不期望的标注或 lint 变化(比如某个历史人名突然不再被标记),那正说明词典或规则层发生了行为漂移,应当先查因再提交快照,而不是盲目接受新快照。

小结

  • Computer science.md 是 Harper 词法标注与 lint 管线的黄金回归语料:CC BY-SA 4.0 许可的维基条目节选,头部注释被词法层识别为Unlintable以屏蔽噪声;
  • 它由 snapshot.rs 的目录扫描机制统一调度,产出 tagged 快照(逐词 POS 对齐标注,图例见 pos_tags.rs)与 lint 快照(Capitalization 127、Style 31、Spelling 63、Readability 127 四类规则的真实触发记录);
  • 快照不一致即测试失败的设计使这份 508 行语料成为 CI 回归闸门的一部分:任何分词、词典、标注或 lint 规则的行为漂移,都会以可逐行审查的 diff 形式暴露出来。

【免费下载链接】harperOffline, privacy-first grammar checker. Fast, open-source, Rust-powered项目地址: https://gitcode.com/GitHub_Trending/har/harper

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询