Metadata-Version: 2.4
Name: mutation-gate
Version: 0.1.0
Summary: 多语言变异测试质量门禁 CLI 工具
License: MIT
Requires-Python: >=3.10
Requires-Dist: click<9.0,>=8.1
Requires-Dist: prompt-toolkit<4.0,>=3.0
Provides-Extra: dev
Requires-Dist: mutmut<3.0,>=2.4; extra == 'dev'
Requires-Dist: pytest-cov<6.0,>=5.0; extra == 'dev'
Requires-Dist: pytest<9.0,>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# mutation-gate

多语言变异测试质量门禁 CLI 工具。支持 Python（mutmut）、Java（pitest）、JavaScript/TypeScript（Stryker）三种后端，输出 PASS/FAIL 裁定和存活变异体列表，可直接嵌入 CI 流水线。

---

## 安装

```bash
pip install mutation-gate
```

开发环境：

```bash
git clone <repo>
pip install -e '.[dev]'
```

**外部依赖**（按语言选装）：

| 语言 | 工具 | 安装 |
|------|------|------|
| Python | mutmut | `pip install mutmut` |
| Java | Maven + JDK | `apt install maven openjdk-21-jdk` |
| JS/TS | Node.js + npm | [nodejs.org](https://nodejs.org)，项目内 `npm install @stryker-mutator/core @stryker-mutator/jest-runner` |

---

## 快速上手

### Python — mutmut

```bash
# 执行变异测试，通过阈值 80%
mutation-gate run --paths src/calc.py --threshold 80

# 查询上次结果（不重新执行）
mutation-gate check --paths src/calc.py --threshold 80
```

### Java — pitest

项目需包含 `pitest-maven` 插件（见 pom.xml 示例）。

```bash
mutation-gate run \
  --paths src/main/java/com/example/Calculator.java \
  --threshold 75

# 多个文件
mutation-gate run \
  --paths src/main/java/com/example/Calculator.java \
  --paths src/main/java/com/example/StringUtils.java \
  --threshold 75
```

### JavaScript / TypeScript — Stryker

项目根目录需有 `stryker.config.json`。

```bash
# JS（自动检测后端）
mutation-gate run --paths src/calc.js --threshold 70

# TypeScript
mutation-gate run --paths src/stack.ts --threshold 70

# 强制指定后端
mutation-gate run --paths src/app.js --tool stryker --threshold 70
```

---

## 命令参考

### `run` — 执行变异测试

```
mutation-gate run [选项]

必选:
  -p, --paths TEXT        源文件路径（可多次指定）

常用选项:
  --threshold FLOAT       通过阈值，默认 80.0%
  --tool TEXT             强制后端：mutmut / pitest / stryker
  --json                  以 JSON 格式输出（供 CI 解析）
  --clean                 执行前先清除旧缓存
  --show-survivors INT    展示 survivor 数量（0=全部，-1=不展示）
  --coverage TEXT         coverage.json 路径（开启覆盖率联合门禁）
```

**示例输出：**

```
## Mutation Gate: PASS

| 指标     | 值           |
|----------|-------------|
| Score    | 81.8%       |
| Threshold| 70.0%       |
| Killed   | 18          |
| Survived | 4           |
| Total    | 22          |
| Scope    | Calculator.java |

### Survivors

- `Calculator.java:33` [ConditionalsBoundaryMutator] changed conditional boundary
```

### `check` — 查询缓存结果（不重新执行）

```bash
mutation-gate check --paths src/calc.py --threshold 80
mutation-gate check --paths src/calc.py --threshold 80 --json
```

缓存位置：`.mutmut-cache`（mutmut）、`target/pit-reports/mutations.xml`（pitest）、`reports/mutation/mutation.json`（Stryker）。

### `status` — 查询运行状态

```bash
mutation-gate status          # 文本格式
mutation-gate status --json   # JSON 格式
```

### `clean` — 清除缓存

```bash
mutation-gate clean              # 自动检测后端
mutation-gate clean --tool pitest
```

---

## 覆盖率联合门禁

先用 `pytest-cov` 生成覆盖率报告，再传给 `run` 或 `check`：

```bash
pytest --cov=src --cov-report=json:coverage.json

mutation-gate run \
  --paths src/calc.py \
  --threshold 80 \
  --coverage coverage.json
```

输出额外显示行覆盖率和分支覆盖率，任一未达标则裁定 FAIL。

---

## REPL 交互模式

无子命令启动进入交互式 shell，支持 Tab 补全和历史记录：

```bash
mutation-gate
```

```
╔══════════════════════════════╗
║  mutation-gate  v0.1.0       ║
║  输入 help 查看可用命令       ║
╚══════════════════════════════╝
> run --paths src/calc.py
> check --paths src/calc.py --json
> quit
```

---

## 退出码

| 退出码 | 含义 |
|--------|------|
| `0` | PASS — 变异分数达标 |
| `1` | FAIL — 变异分数低于阈值 |
| `2` | ERROR — 工具未安装 / 缓存不存在 / 参数错误 |

---

## CI 集成示例

```yaml
# GitHub Actions
- name: Mutation Gate
  run: |
    mutation-gate run \
      --paths src/calc.py \
      --threshold 80 \
      --json
```

`--json` 输出结构：

```json
{
  "verdict": "FAIL",
  "score": 57.14,
  "threshold": 80.0,
  "killed": 4,
  "survived": 3,
  "total": 7,
  "scope_files": ["src/calc.py"],
  "survivors": [
    {"file": "src/calc.py", "line": 13, "mutator": "mutmut",
     "description": "--- src/calc.py\n+++ ..."}
  ]
}
```

---

## 打包与发布

### 依赖

```bash
pip install build twine
```

### 构建

```bash
python -m build
```

在 `dist/` 下生成两个文件：

```
dist/
  mutation_gate-0.1.0-py3-none-any.whl   # 二进制分发包（推荐安装）
  mutation_gate-0.1.0.tar.gz             # 源码包
```

Wheel 仅含 `src/mutation_gate/` 运行时代码，不包含测试和文档。

### 验证

```bash
# 检查包元数据是否符合 PyPI 规范
twine check dist/*

# 在隔离环境中测试安装
python -m venv /tmp/test-env
/tmp/test-env/bin/pip install dist/mutation_gate-0.1.0-py3-none-any.whl
/tmp/test-env/bin/mutation-gate --help
```

### 发布到 PyPI

```bash
# 正式发布
twine upload dist/*

# 先在测试仓库验证
twine upload --repository testpypi dist/*
pip install --index-url https://test.pypi.org/simple/ mutation-gate
```

### 升版本号

版本号在 `pyproject.toml` 中统一维护：

```toml
[project]
version = "0.2.0"
```

改完后重新构建即可，无需其他修改。

### 项目元数据（`pyproject.toml` 关键字段）

```toml
[build-system]
requires = ["hatchling>=1.21"]      # 构建后端
build-backend = "hatchling.build"

[project]
name = "mutation-gate"              # PyPI 包名
version = "0.1.0"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
    "click>=8.1,<9.0",
    "prompt-toolkit>=3.0,<4.0",
]

[project.scripts]
mutation-gate = "mutation_gate.cli:main"   # CLI 入口点

[tool.hatch.build.targets.wheel]
packages = ["src/mutation_gate"]    # 只打包运行时代码
```
