Bhavikupadhyay/coverage-agent
GitHub: Bhavikupadhyay/coverage-agent
一个基于多智能体的 Python 测试自动生成 pipeline,通过分析分支覆盖缺口并利用确定性验证关卡确保生成的 pytest 测试真实有效。
Stars: 1 | Forks: 0
# CoverageAgent
一个多智能体 pipeline,它能在你的 PR 中找出未被覆盖的 Python 分支,为其编写有针对性的 pytest 测试,并在提交给你之前通过实际执行来验证每一个测试。
  
只有当三个确定性关卡达成一致时,测试才会被保留:pytest 在每次重复中均通过,coverage 数据证明目标 arc 已被执行,以及仓库现有的完整测试套件依然通过。LLM 永远不会评判自己的工作。
## 在 pull request 上使用
```
# .github/workflows/coverage-agent.yml
name: coverage-agent
on: pull_request
permissions:
pull-requests: write
jobs:
coverage-agent:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # the diff base must be resolvable
- uses: astral-sh/setup-uv@v5
# Install YOUR project and put its venv first on PATH — generated
# tests execute in your environment, with your dependencies.
- name: Install project
run: |
uv sync
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- uses: Bhavikupadhyay/coverage-agent@main
with:
llm-api-key: ${{ secrets.LLM_API_KEY }}
model: groq/llama-3.3-70b-versatile # free tier works
```
在每个 PR 上,它都会与 base 分支进行 diff,找出没有测试执行的新增或更改代码,为其生成测试,在 runner 上进行验证,并发布一条包含结果和测试文件 diff 的评论。该评论在后续推送时会被原地更新,绝不重复。添加 `commit-mode: commit`(以及 `contents: write`)可以将通过的测试直接提交到 PR 分支中。
[本仓库的 PR #2](https://github.com/Bhavikupadhyay/coverage-agent/pull/2) 是一个真实的示例:该 PR 添加了一个没有测试的模块,Action 为其生成了五个经过验证的测试并发布了出来——使用的是本仓库自己的 workflow 文件以及一个免费的 Groq key。
## 实测结果
以下每个数字均来自真实运行。最终运行的原始 `RunReport` JSON 存放在 [`benchmarks/results/`](benchmarks/results/) 中;没有任何数据是预估的。
| 运行 | 模型 (免费层) | 结果 |
|---|---|
| 已知答案基准测试,diff 范围 | Groq llama-3.3-70b | 接受 3/3 缺口 |
| 已知答案基准测试,全范围 | Groq llama-3.3-70b | 接受 9/9 缺口 |
| 已知答案基准测试,双范围 | Gemini 2.5 Flash | 接受 10/12 缺口 |
| 本仓库的代码库,全范围 | Groq llama-3.3-70b | 单次运行接受 5 个缺口,包含一个 5-arc 簇;完整测试套件保持绿色 |
| 实时 PR ([#2](https://github.com/Bhavikupadhyay/coverage-agent/pull/2)) | Groq llama-3.3-70b | 发布了 5 个已验证测试;评论在 2 次运行中执行了 upsert |
已知答案基准测试是一个合成的 package,恰好包含 12 个已知存在覆盖测试的未覆盖 arc;它在每次 push 时针对 mock LLM 运行,并在发布前针对真实的 key 进行测试。[`tests/generated/`](tests/generated/) 下的测试是由 agent 为本仓库编写的,现已成为测试套件的一部分。
对于免费层级的 key 而言,两个设计选择至关重要。同一函数中的缺口会被聚集到一次会话中,因此 LLM 请求量随着受影响的函数数量而不是发现的 arc 数量而扩展(在本仓库的一次 10 缺口运行中仅使用了 3 次会话)。此外,writer 在提交前必须使用其 `run_candidate` 工具验证其草稿,这也是高接受率的主要来源。
## Pipeline
```
---
config:
flowchart:
curve: linear
---
graph TD;
__start__([ # or GEMINI_API_KEY etc.
export COVERAGE_AGENT_MODEL=groq/llama-3.3-70b-versatile
# 在当前 checkout 上运行(如果未找到 .coverage 文件,则自动运行 coverage)
coverage-agent run --scope full --max-gaps 5
# 仅针对自某个 ref(分支、SHA 或 commit range base)以来的更改
coverage-agent run --scope diff --base origin/main
coverage-agent run --scope diff --base HEAD~3
# 写入 RunReport JSON,格式化打印并列出 models
coverage-agent run --scope full --max-gaps 5 --output report.json
coverage-agent report report.json
coverage-agent models
```
## 配置
在你的仓库根目录下放置一个 `.coverage-agent.yml` 文件。所有字段均为可选。
```
version: 1
model: groq/llama-3.3-70b-versatile # any litellm model string
scope: diff # diff | full
max_gaps: 10
test_command: pytest -q
tests_dir: tests/generated
flaky_runs: 3
test_timeout: 60
exclude:
- "**/migrations/**"
- "**/conftest.py"
- "tests/**"
- "test_*.py"
```
## 模型
支持 [`coverage_agent/models.json`](coverage_agent/models.json) 中的任何模型 —— Gemini、OpenAI、Anthropic、Groq、xAI、Cerebras、Mistral。传入 `--model ` 进行覆盖。对于标记为 `tool_calling: true` 的模型,将激活 ReAct 工具循环;其他模型则退回到单次生成。来自真实运行的免费层提示:Groq 的免费层处理了本 README 中的所有基准测试;Gemini 的免费层每天限制 20 次请求,仅够小型 PR 使用。
## 测试
```
uv run pytest -q
# 158 个测试,约 20 秒,无 network calls,无 keys
python benchmarks/run_acceptance.py --mock-llm # the known-answer benchmark, also key-free
```
## 许可证
Apache 2.0 —— 见 [`LICENSE`](LICENSE)。
__start__
]):::first context_architect(context_architect) gap_filter(gap_filter) test_writer(test_writer) eval_agent(eval_agent) execution_runner(execution_runner) accept(accept) skip(skip) __end__([__end__
]):::last __start__ --> context_architect; context_architect --> gap_filter; eval_agent -. CONTEXT_ARCHITECT .-> context_architect; eval_agent -. EXECUTION_RUNNER .-> execution_runner; eval_agent -. SKIP .-> skip; eval_agent -. TEST_WRITER .-> test_writer; execution_runner -. ACCEPT .-> accept; execution_runner -. SKIP .-> skip; execution_runner -. TEST_WRITER .-> test_writer; gap_filter --> test_writer; test_writer --> eval_agent; accept --> __end__; skip --> __end__; classDef default fill:#f2f0ff,line-height:1.2 classDef first fill-opacity:0 classDef last fill:#bfb6fc ``` | 节点 | 功能 | |---|---| | **context_architect** | Jedi 遍历:将目标函数源码 + 被调用者签名组装成 `ContextPayload` (≤15k tokens) | | **gap_filter** | 基于 IO 密集型符号和上下文 token 数量标记缺口难度 (`easy`/`hard`) | | **test_writer** | ReAct agent:结合 litellm 函数调用,使用 `read_source`、`find_symbol`、`find_usages` 和 `run_candidate` —— 它必须执行自己的草稿并在提交前看到目标被命中 | | **eval_agent** | 确定性关卡:`ast.parse` 语法检查 + 导入合理性检查;路由至 EXECUTE、REWRITE 或 RECONTEXTUALIZE | | **execution_runner** | 运行 `coverage run --branch -m pytest`;在 coverage 数据中验证每个簇 arc;重复执行 `flaky_runs` 次 | | **accept / skip** | 终端节点;失败的执行会将其 stderr 作为下一次反馈提供给 writer | 一个 LLM agent,多个确定性执行者:只有 `test_writer` 会调用模型。验证、路由和回归检查全部都是模型无法影响的机制。 ## CLI ``` git clone https://github.com/Bhavikupadhyay/coverage-agent.git cd coverage-agent uv sync export GROQ_API_KEY=标签:AI智能体, Python, SOC Prime, 代码覆盖率, 安全规则引擎, 开发工具, 开源框架, 持续集成, 无后门, 逆向工具