本文目录导读:

Git钩子脚本可以通过以下方式检查测试覆盖率:
基础实现方法
在 pre-commit 钩子中检查覆盖率
#!/bin/bash
# .git/hooks/pre-commit
# 运行测试并生成覆盖率报告
coverage run -m pytest
coverage report
# 提取总覆盖率百分比
COVERAGE=$(coverage report | grep "TOTAL" | awk '{print $NF}' | sed 's/%//')
# 设置覆盖率阈值
THRESHOLD=80
if (( $(echo "$COVERAGE < $THRESHOLD" | bc -l) )); then
echo "❌ 测试覆盖率不达标: ${COVERAGE}% < ${THRESHOLD}%"
exit 1
fi
echo "✅ 测试覆盖率达标: ${COVERAGE}%"
更完整的脚本示例
#!/bin/bash
# .git/hooks/pre-commit
set -e
PROJECT_ROOT=$(git rev-parse --show-toplevel)
cd "$PROJECT_ROOT"
# 配置
MIN_COVERAGE=80
COVERAGE_FILE=".coverage"
REPORT_DIR="coverage_report"
echo "📊 开始检查测试覆盖率..."
# 运行测试并收集覆盖率
coverage run -m pytest tests/ -v 2>&1
# 检查测试是否通过
if [ $? -ne 0 ]; then
echo "❌ 测试失败,请修复后再提交"
exit 1
fi
# 生成覆盖率报告
coverage report -m > coverage_report.txt
# 解析覆盖率
COVERAGE_VALUE=$(coverage report | grep -E "^TOTAL" | awk '{print $NF}' | tr -d '%')
if [ -z "$COVERAGE_VALUE" ]; then
echo "❌ 无法获取覆盖率信息"
exit 1
fi
echo "当前覆盖率: ${COVERAGE_VALUE}%"
# 比较覆盖率
if (( $(echo "$COVERAGE_VALUE < $MIN_COVERAGE" | bc -l) )); then
echo "❌ 覆盖率 ${COVERAGE_VALUE}% 低于阈值 ${MIN_COVERAGE}%"
# 可选:生成HTML报告便于查看
coverage html -d "$REPORT_DIR"
echo "详细报告已生成: $REPORT_DIR/index.html"
exit 1
fi
echo "✅ 覆盖率检查通过: ${COVERAGE_VALUE}%"
# 清理临时文件
rm -f coverage_report.txt
Python 版本的钩子脚本
#!/usr/bin/env python3
# .git/hooks/pre-commit
import re
import sys
import subprocess
import os
def check_coverage():
"""检查测试覆盖率"""
# 设置覆盖率阈值
THRESHOLD = 80
# 运行测试并收集覆盖率
try:
result = subprocess.run(
["coverage", "run", "-m", "pytest", "tests/"],
capture_output=True,
text=True
)
if result.returncode != 0:
print("❌ 测试失败")
print(result.stdout)
print(result.stderr)
return False
# 获取覆盖率报告
result = subprocess.run(
["coverage", "report"],
capture_output=True,
text=True
)
# 解析覆盖率百分比
match = re.search(r'TOTAL\s+\d+\s+\d+\s+(\d+)%', result.stdout)
if match:
coverage = float(match.group(1))
print(f"当前覆盖率: {coverage}%")
if coverage < THRESHOLD:
print(f"❌ 覆盖率 {coverage}% 低于阈值 {THRESHOLD}%")
return False
print(f"✅ 覆盖率检查通过: {coverage}%")
return True
else:
print("❌ 无法解析覆盖率信息")
return False
except Exception as e:
print(f"❌ 检查覆盖时发生错误: {e}")
return False
if __name__ == "__main__":
if not check_coverage():
sys.exit(1)
sys.exit(0)
只检查变更文件的覆盖率
#!/bin/bash
# .git/hooks/pre-commit
# 获取本次变更的Python文件
CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep "\.py$")
if [ -z "$CHANGED_FILES" ]; then
echo "没有Python文件变更,跳过覆盖率检查"
exit 0
fi
echo "变更的文件:"
echo "$CHANGED_FILES"
# 只运行涉及变更文件的测试
coverage run -m pytest tests/ -k "$(echo $CHANGED_FILES | tr '\n' '|')"
# 创建覆盖率报告
coverage report --include="$CHANGED_FILES"
COVERAGE=$(coverage report --include="$CHANGED_FILES" | grep -E "^TOTAL" | awk '{print $NF}' | sed 's/%//')
THRESHOLD=80
if [ -z "$COVERAGE" ]; then
echo "⚠️ 无法获取变更文件的覆盖率信息"
elif (( $(echo "$COVERAGE < $THRESHOLD" | bc -l) )); then
echo "❌ 变更文件覆盖率 ${COVERAGE}% 低于阈值 ${THRESHOLD}%"
exit 1
fi
echo "✅ 覆盖率检查通过"
安装钩子的脚本
创建一个脚本来安装这些钩子:
#!/bin/bash # setup-hooks.sh HOOK_DIR=".git/hooks" TEMPLATE_DIR="githooks" # 创建钩子目录 mkdir -p "$HOOK_DIR" # 复制pre-commit钩子 cp "$TEMPLATE_DIR/pre-commit" "$HOOK_DIR/pre-commit" chmod +x "$HOOK_DIR/pre-commit" echo "✅ Git钩子已安装"
配置文件和高级选项
.coveragerc 配置文件
[run]
source = src
omit =
*/tests/*
*/test_*.py
*/setup.py
[report]
exclude_lines =
pragma: no cover
def __repr__
def __str__
if __name__ == .__main__.:
fail_under = 80
[html]
directory = coverage_report
高级覆盖率检查(包含分支覆盖率)
#!/bin/bash
# 检查分支覆盖率
coverage run --branch -m pytest tests/
# 生成详细报告
coverage report --show-missing --include="src/*"
# 获取分支覆盖率
BRANCH_COVERAGE=$(coverage report --show-missing | grep "TOTAL" | awk '{print $6}' | sed 's/%//')
LINE_COVERAGE=$(coverage report --show-missing | grep "TOTAL" | awk '{print $4}' | sed 's/%//')
echo "行覆盖率: ${LINE_COVERAGE}%"
echo "分支覆盖率: ${BRANCH_COVERAGE}%"
# 可以分别检查行覆盖率和分支覆盖率
if (( $(echo "$LINE_COVERAGE < 80" | bc -l) )); then
echo "❌ 行覆盖率不达标"
exit 1
fi
if (( $(echo "$BRANCH_COVERAGE < 70" | bc -l) )); then
echo "❌ 分支覆盖率不达标"
exit 1
fi
使用建议
- 选择合适的位置:建议使用
pre-commit钩子,在提交前检查 - 设置合理的阈值:根据项目情况设置 70%-90% 的阈值
- 考虑性能:大型项目可以只检查变更的文件
- 跳过机制:允许特殊情况跳过检查(如紧急修复)
# 跳过钩子的方法 git commit -m "紧急修复" --no-verify # 或 SKIP=coverage git commit -m "跳过覆盖率检查"
这样可以在保证代码质量的同时,不影响开发效率。