关于 mutation-testing
用于 Metabase 开发环境中 Clojure 命名空间变异测试的技能。它调用 Claude 编写测试并验证变异是否被捕获,还会协调创建 Linear 问题和草稿 PR。
主要功能
- 01生成变异覆盖率报告
- 02按覆盖关系分组函数
- 03调用 Claude 编写测试
- 04验证变异并重试分组
- 05创建 Linear 问题和草稿 PR
适用场景
- 01评估命名空间的变异覆盖率
- 02编写测试并跟踪后续工作
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ metabase/ metabase --skill mutation-testing安装后在 Claude Code 中输入/mutation-testing确认已加载。
详细介绍
变异测试 Skill
此 skill 端到端运行变异测试:生成覆盖率报告、对函数分组、调用 claude -p 编写测试、验证变异是否被杀死,并创建带有 Linear issue 的草稿 PR。
前提条件
- 一个连接到 Metabase 开发环境的运行中的 nREPL
- 已设置
LINEAR_API_KEY环境变量,且其中包含有效的 Linear 个人 API key - 已通过 GitHub 认证的
ghCLI - PATH 中可用的
claudeCLI
参考文件
dev/src/dev/coverage.clj— 变异测试引擎(生成报告、运行变异)dev/src/dev/mutation_testing.clj— 编排、Linear API、PR 辅助工具
调用
参数是一个 Clojure 命名空间,后面可选跟一个基础分支:
/mutation-testing metabase.lib.order-by
/mutation-testing metabase.lib.order-by --base-branch release-x.52.x
/mutation-testing metabase.lib.order-by --project-id abc-123
/mutation-testing metabase.lib.order-by --base-branch release-x.52.x --project-id abc-123
--base-branch:默认为配置中的值(通过set-config!设置),如果未配置则为"master"。--project-id:如果提供,issue 会被添加到这个已有的 Linear 项目中,而不是创建一个新的。
步骤
1. 解析参数
解析 $ARGUMENTS 以提取:
- namespace(必需)— 第一个位置参数
--base-branch(可选)— 如果存在,下一个参数是基础分支名称--project-id(可选)— 如果存在,下一个参数是已有的 Linear 项目 ID
2. 加载并配置
(require '[dev.mutation-testing :as mut-test] :reload)
(require '[dev.coverage :as cov] :reload)
如果这是首次调用(或者 REPL 已重启),设置 Linear 团队:
(mut-test/list-teams!)
(mut-test/set-config! {:team-id "<id>"})
3. 运行
(mut-test/run! '<target-ns>)
;; Or with options:
(mut-test/run! '<target-ns> {:base-branch "release-x.52.x"})
(mut-test/run! '<target-ns> {:project-id "abc-123"})
(mut-test/run! '<target-ns> {:base-branch "release-x.52.x" :project-id "abc-123"})
如果参数中提供了这些标志,则传入带有 :base-branch 和/或 :project-id 的 opts map。
这将:
- 生成基线变异测试报告
- 为该命名空间创建一个 Linear 项目
- 按覆盖率关系对函数分组
- 对每个分组:创建分支 → 调用 Claude 编写测试 → 验证 → 如需要则重试 → 提交并推送 → 创建 Linear issue → 创建草稿 PR
- 打印带有 PR 链接的摘要
4. 处理失败
如果某个分组在处理过程中失败,run! 会捕获错误并继续处理下一个分组。要手动重试单个分组:
;; Get the parsed namespace info
(def parsed (mut-test/parse-namespace '<target-ns>))
;; Run coverage to get the data
(def coverage-results (cov/test-namespace (:target-ns parsed) [(:test-ns parsed)]))
;; Group and find the one you want
(def groups (mut-test/group-functions coverage-results))
;; Process just that group
(mut-test/process-group! parsed (nth groups <index>))
5. 验证提示词(dry run)
要在不调用 Claude 的情况下查看它将看到的内容:
(def parsed (mut-test/parse-namespace '<target-ns>))
(def coverage-results (cov/test-namespace (:target-ns parsed) [(:test-ns parsed)]))
(def groups (mut-test/group-functions coverage-results))
(println (mut-test/build-test-prompt
(merge (select-keys parsed [:target-ns :test-ns :source-path :test-path])
(select-keys (first groups) [:fn-names :mutations]))))
配置
- Team ID:每个 REPL 会话通过
(mut-test/list-teams!)和(mut-test/set-config! {:team-id "..."})设置一次 - Project ID:当
run!调用create-project-for-namespace!时自动设置 - Base Branch:默认为
"master"。可通过(mut-test/set-config! {:base-branch "release-x.52.x"})覆盖,或将{:base-branch "..."}作为第二个参数传给run! - Project ID:如果已设置(通过
set-config!或run!opts),run!会复用已有的 Linear 项目,而不是创建一个新的
评论
支持 Markdown