Skip to main content
Glama
test-trust
by rrudy9

test-trust

让 AI 编程代理(Claude Code、Codex、OpenHands、Cursor 或本地模型——通过 MCP(Model Context Protocol)实现与代理无关)不仅知道哪些测试覆盖了某个更改,而且知道这些测试是否真的能被信任,能在相应位置捕获回归。

如今每个代理都把“CI 通过”和“这个更改是安全的”当作同一回事。但它们不是。覆盖某个函数的测试,不等于该函数损坏时实际会失败的测试——过度 mock 的测试、只是重新记录新输出的快照测试,以及没有断言的测试,都会显示通过,却什么都抓不住。

原理

  1. 变异测试(封装成熟现有引擎,而非重新实现——Python 用 mutmut,JS/TS 用 StrykerJS,Go 用 gremlins,Rust 用 cargo-mutants):有意向更改后的代码中引入小错误,检查覆盖测试是否真的失败。每个变异体的测试选择来自各引擎自身的覆盖数据,而不是在这里重新实现——mutmut 和 Stryker(在受支持的 runner 下:jest/mocha/vitest)只选择覆盖每个变异体的具体测试;gremlins 和 cargo-mutants 会跳过零覆盖的变异体,但对任何有覆盖的变异体重新运行完整的相关测试套件,这是一种更粗糙(在大型代码库上更慢)但仍然正确的机制。

  2. 差异范围限定(我们的):通过每种语言自身的解析,将 git diff 的更改行映射到所属函数,因此变异运行和信任分数都限定在实际更改的内容上,而不是整个文件/仓库。

  3. 融合(新的部分,其他地方没有实现——已验证):将上述内容合并为每个被更改函数的一个信任分数,作为一个 MCP 工具暴露出来,任何代理都可以在把测试通过视为安全证据之前调用它。

参见 examples/weak-test-fixture/(Python)、examples/weak-test-fixture-js/(JS)、examples/weak-test-fixture-go/(Go)、examples/weak-test-fixture-rust/(Rust)、examples/plug-and-play-fixture/(完全零配置)以及 examples/multi-file-fixture-js/(一个导入同级模块的函数,证明变异范围限定不会破坏跨文件导入),这些是可运行的实际演示:一个函数被某个测试覆盖,该测试今天能通过,但抓不住真正的 bug。

Related MCP server: sumo-qa

针对真实仓库验证,而不仅仅是 fixture

上面的每个 fixture 都是玩具。在相信这个概念之前,这项工作还以零配置方式针对四种语言的真实、外部、未修改的仓库运行过:psf/requests(Python,对 37 个真实函数进行了评分,例如 resolve_proxies 在信任分数 0.0 时被正确标记——确实没有任何测试引用它)、kind-of(JS,每周下载量约 50M,isArray 和 isRegexp 被标记,尽管全部 36 个测试都通过)、dustin/go-humanize(Go)以及 chronotope/humantime(Rust,一个真正的多模块 crate——证实变异范围限定在真实的跨模块代码上不会出问题,而不仅限于我们自己的 fixture)。这个过程在四个语言中的三个中捕获并修复了几个真实 bug——其中一个是一次失败的变异运行被静默报告为虚假的 100% 信任分数,还有一个扩展性 bug:一个限定到单个文件的请求反而静默地变异了整个真实包。Rust 的真实仓库检查没有发现新 bug,这与 cargo-mutants -f 是四种机制中最干净、最直接受支持的范围限定机制一致。完整说明见 docs/architecture.md。

此工具封装的外部工具(按你使用的语言安装一次)

  • Python:mutmut——作为本项目依赖自动安装。

  • JS/TS:@stryker-mutator/core——首次使用时通过 npx 自动获取。

  • Go:gremlins——go install github.com/go-gremlins/gremlins/cmd/gremlins@latest

  • Rust:cargo-mutants——cargo install cargo-mutants

试用

尚未发布到 PyPI。 下面的每个命令都假定你已本地克隆此仓库,并在仓库内运行(从外部运行则使用 uv run --directory <path> ...,如下面的代理嵌入示例所示)。一旦发布,这些都将简化为普通的 pip install test-trust / uvx test-trust,可在任何地方运行——无需克隆、无需记住路径、无需 uv run --directory。这唯一的改变是从“能工作,但需要安装配置”到“真正易于采用”的最后一步;工具的行为没有任何变化,变的只是你获得它的方式。

需要 Python 3.11+ 和 uv。各语言的变异引擎(见上文)仅在你实际使用的语言中才需要——下面的 Python 示例除了 uv sync 之外什么都不需要。

uv sync
uv run test-trust check examples/plug-and-play-fixture inventory.py

无需配置文件,无需手动运行变异测试——这条命令会自动检测语言、自动写入配置、使用仓库自身真实的测试命令自动运行限定到该文件的变异测试,并输出信任分数。

要对其他文件或仓库运行:

uv run test-trust check <path-to-repo> <source-file> [--changed-file F] [--base-ref REF] [--threshold T]

更改阈值(默认 0.5)——决定什么算作经过充分测试。提高它(例如 0.8)以标记任何未接近完全变异覆盖的情况;降低它则只标记最严重的缺口。同一个参数,三种使用方式:

  • CLI:--threshold 0.8,如上所示。

  • MCP 工具:threshold 是 get_test_trust 的一个参数,例如 get_test_trust(repo_path=..., source_file=..., threshold=0.8)。你不需要自己调用它——代理会调用——所以设置它意味着告诉代理(在你的提示词中,或作为 CLAUDE.md 中的常设指令:“call get_test_trust with threshold=0.8”)。未设置时,使用 0.5。

  • GitHub Action:工作流文件中的 low-trust-threshold 输入:

    - uses: ./.github/actions/test-trust-pr
      with:
        github-token: ${{ secrets.GITHUB_TOKEN }}
        low-trust-threshold: "0.8"

嵌入代理

一次性设置,注册为全局而非按项目——因为 repo_path 是每次调用上的参数,而不是在启动时固定,一次注册即可服务于你之后打开的每个项目,而不仅仅是当初设置的那个项目。对于 Claude Code,添加到 ~/.claude.json(用户级,而不是项目的 .mcp.json):

{
  "mcpServers": {
    "test-trust": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/to/test-trust", "test-trust", "mcp"]
    }
  }
}

相同的 command/args 形式适用于 Codex、Cursor 或任何其他 MCP 客户端——有关这些内容以及一旦发布到 PyPI 会发生什么变化(uvx test-trust mcp,完全不需要本地路径),请参阅 docs/embedding.md。

之后它在日常使用中是无感的:代理会在任务中途自行调用 get_test_trust,就像它已经在调用文件读取或 bash 工具一样——你不需要直接调用它。

或者在每个 PR 上运行,无需代理

.github/actions/test-trust-pr 会为 PR 中每个更改过的、受支持的文件打分,并发布(或在后续推送时更新)一条评论——标记任何现有测试实际上无法捕获该处回归的函数。任何做代码审查的团队都有用,无论是否有人使用 AI 代理。.github/workflows/test-trust.yml 是工作示例;已针对真实仓库中的真实提交进行了端到端验证(diff 检测、评分、“全部通过”和“已标记”两种评论渲染)——只有实时 GitHub API 调用本身未测试,因为这需要实际的 PR 才能验证。

开发

uv sync
uv run pytest tests/            # this project's own unit test suite
uv run test-trust check <repo> <file>   # exercise it against real code

tests/ 用精心构造的 fixture 覆盖确定性逻辑(diff 范围限定、信任分数聚合、语言自动检测、每个变异引擎的报告适配器)——速度快,不需要外部变异测试工具,而且这个套件正是 CI(.github/workflows/ci.yml)中实际运行的。它不能替代上面的真实仓库验证——那是在开发期间进行的一次性手动工作(真实外部克隆、安装了真实引擎),不是 CI 在每次推送时重新运行的内容。值得以后自动化;但还没有做。

MIT 许可证。

Related MCP Connectors

Related MCP Servers