dots测试与发布实践:单元测试、pin守护测试与pre-push钩子门禁完整清单
【免费下载链接】dotsOpen-source dots for the web: an AI agent with its own browser, one that does not get blocked.项目地址: https://gitcode.com/gh_mirrors/dots140/dots
dots 是一个把 AI agent 装进真实 Firefox 浏览器的开源项目(MIT 协议),它本身只有 3 个源码文件,却配了一整套严肃的测试与发布门禁:4 个 pytest 用例、一条“精确 pin 的依赖守护测试”、一个 pre-push 钩子门禁,外加 CI 矩阵复核。对新手来说,这套结构是理解“如何用最小代码量守住发布质量”的绝佳样本。
🧪 一、测试基座:两个 marker 划清边界
pytest 的配置直接写在 pyproject.toml 里,用两个 marker 把用例分成两类:
| Marker | 含义 |
|---|---|
unit | 纯逻辑——无 I/O、无网络、无子进程、无浏览器 |
integration | 在子进程里跑真实命令——依然不碰网络和浏览器 |
配合--strict-markers保证没人能偷偷漏打标,pythonpath = ["src"]让测试直接指向 src/dots 源码包。
🔍 二、4 个测试用例,各守一道门
全部用例集中在 tests/test_entry.py,一个文件讲完整个守护逻辑:
- 参数前置正确(
unit):test_the_group_is_called_with_ui_in_front 用 monkeypatch 替换底层命令组,断言dots --port 9000 --headed最终变成ui --port 9000 --headed且程序名仍是dots。为什么必须经过命令“组”而不是直接调ui?因为.env里的密钥是在组那一层读取的,绕过去就会悄悄失效。 - help 即接口(
integration):test_help_is_the_interface_help 在干净环境里真跑python -m dots --help,确认--openrouter-key、--seed、--proxy等选项都在——用户看到的帮助页就是产品的真实接口。 - 没密钥就拒启动(
integration):test_without_a_key_it_refuses_before_starting_anything 验证无 key 时程序立刻报错,而不是先起浏览器再尴尬失败。 - pin 守护(
unit):见下一节。
📌 三、pin 守护测试:依赖悄悄换货怎么办?
pyproject.toml 里有句狠话:“整个产品就是这一行”——invisible-playwright-mcp==0.70.2。浏览器循环、页面、命令组全部来自这个包,而它提供的命令组不是公开 API,所以依赖必须用==精确 pin 而非>=下限:版本只能人为升级,绝不让 resolver 顺手拉新。
守护它的就是 test_the_installed_package_is_the_pinned_one:读出 pyproject 里 pin 的版本号,再查环境中实际安装的版本,两者不一致立刻红灯。注释还点出另一种偷渡方式——把兄弟目录的 editable 安装装进来,会让前面所有测试“测错对象”,而这个用例能直接识破。
升级流程一句话:改 pin → 跑 tests/test_entry.py → 全绿才合入。
🚪 四、pre-push 钩子门禁:薄脚本,厚策略
.githooks/pre-push 只有 55 行,且策略不写在钩子里:
- 脚本唯一职责是找到 Python 解释器,然后
exec交给invisible_core.hooks(随 pin 的包一起进来)执行检查,stdin(git 推送的 refs)原样透传; - 本仓库要开哪些门禁,声明在 pyproject.toml 的
[tool.invisible.hooks]:pytest = true、english = true(英文行文检查)、identity = true(身份信息一致性),pin = false且release_tags = []——因为本仓库不发布 release tag; - 找不到 Python 或导入失败时,钩子拒绝推送并给出可读的报错,而不是静默放行——“不能检查,就不能推送”。
安装一次即可,忘记也没关系:
git config core.hooksPath .githooks唯一逃生门是git push --no-verify,只给“已知坏掉的 WIP 分支”用,发布分支禁用。另外 .gitattributes 强制.githooks/**保持 LF,专治 Windows 上 CRLF 导致的/bin/sh^M: bad interpreter。
🛡️ 五、第二道防线:CI 矩阵与 gate 汇总
.github/workflows/tests.yml 在每次 push / PR 时再跑一遍:
| Job | 作用 |
|---|---|
english/claims | 校验文档行文与 README 的承诺不夸大 |
unit | 矩阵:Ubuntu × Python 3.11/3.12/3.13 + Windows × 3.12,与requires-python = ">=3.11"的承诺对齐(见 矩阵定义) |
gate | 依赖全部 job,且只接受 success,任何 skipped 都算失败(gate 汇总) |
细节值得抄作业:pytest 后还会解析报告,通过的用例少于 4 个直接判负——防止“筛选条件写错导致 0 个用例运行”被误当成全绿(拒自我 deselection)。
📋 六、测试与发布完整清单
| 层级 | 检查项 | 位置 |
|---|---|---|
| 本地开发 | 2 个 unit + 2 个 integration 用例 | tests/test_entry.py |
| 本地开发 | 依赖 pin 版本一致性 | pyproject.toml |
| pre-push 钩子 | pytest / english / identity | .githooks/pre-push + 钩子开关 |
| CI | 英文行文、claims、双 OS 多版本矩阵 | .github/workflows/tests.yml |
| CI | gate 汇总,skip 即失败 | gate job |
| 发布策略 | 精确 pin 手动升级,无 release tag | pyproject.toml |
🚀 七、三步在本地跑起来
git clone https://gitcode.com/gh_mirrors/dots140/dots cd dots pip install -e ".[dev]" # dev 依赖仅 pytest>=7 pytest tests/ -v # 预期:4 passed git config core.hooksPath .githooks # 装上门禁小结
dots 给出的方法论非常清晰:测试不追求多,而追求每个用例都有明确要守的东西(参数前置、help 即接口、缺 key 即拒、pin 一致);钩子脚本保持薄,策略下沉为可共享的包;本地门禁 + CI 矩阵双保险,连“0 个用例运行”这种隐性失败都防住了。小项目完全可以照单复制这套骨架。
【免费下载链接】dotsOpen-source dots for the web: an AI agent with its own browser, one that does not get blocked.项目地址: https://gitcode.com/gh_mirrors/dots140/dots
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考