Files
cobol-java-v3/tests/test_gcov_basic.py
T
hangshuo652 bc1d56d1a4 feat: Phase 2 complete — 13 Phases of COBOL type classification and test benchmark
P0.6: gcov infrastructure
P1: extract_structure output expansion (11 new feature fields)
P2: Confusion group rule engine (8 pairs + contradiction + backtrack)
P3: 4-factor confidence calculation + quality gate update
P4: 33+2 COBOL program type test samples (22 files, 7 categories)
P5: parametrized/ test data generation engine
P6: japanese_data.py lookup tables
P7-10: Type-specific test suites (~159 parametrized tests)
P11: Full classification pipeline (classify_program) + orchestrator integration
P12: Documentation (module-interfaces, test-plan v3.0, coverage-matrix)

Architecture decisions:
- classification_pipeline/ merged to hina/pipeline/
- parametrized/ as independent module
- japanese_data.py as root-level file
- hina/__all__ only exports classify_program()

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-19 23:51:55 +08:00

153 lines
4.8 KiB
Python

"""gcov 覆盖率采集全链路测试
测试内容:
1. cobc --coverage 编译含 IF 分支的简单 COBOL 程序
2. 运行生成 .gcda 文件
3. collect_gcov() 解析 line_rate > 0
4. 清理中间产物
"""
import sys, os, subprocess, tempfile
from pathlib import Path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
import pytest
from hina.gcov_collector import collect_gcov
HAVE_COBC = None
def _check_cobc() -> bool:
"""检查 cobc 是否在 PATH 且支持 --coverage"""
global HAVE_COBC
if HAVE_COBC is not None:
return HAVE_COBC
try:
r = subprocess.run(["cobc", "--version"], capture_output=True, text=True, timeout=15)
HAVE_COBC = r.returncode == 0
except FileNotFoundError:
HAVE_COBC = False
return HAVE_COBC
# ── 嵌入一个简单的 COBOL 程序 (IF 分支) ──
SAMPLE_COBOL = """\
IDENTIFICATION DIVISION.
PROGRAM-ID. test-gcov.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-X PIC 9(2) VALUE 0.
01 WS-Y PIC 9(2) VALUE 0.
PROCEDURE DIVISION.
MOVE 10 TO WS-X.
IF WS-X > 5 THEN
MOVE 1 TO WS-Y
ELSE
MOVE 2 TO WS-Y
END-IF.
DISPLAY "Y=" WS-Y.
STOP RUN.
"""
# ── 夹具: 创建临时目录存放 COBOL 源和编译产物 ──
@pytest.fixture
def work_dir() -> Path:
"""创建临时工作目录"""
with tempfile.TemporaryDirectory(prefix="gcov_test_") as tmp:
yield Path(tmp)
# ── 辅助函数 ──
def _compile_with_coverage(src_path: Path, out_dir: Path) -> bool:
"""用 cobc --coverage 编译, 返回是否成功"""
r = subprocess.run(
["cobc", "-x", "--coverage", str(src_path), "-o", str(out_dir / "test-gcov.exe")],
capture_output=True, text=True, timeout=30,
cwd=str(out_dir),
)
if r.returncode != 0:
print(f"[compile] stderr: {r.stderr[:300]}")
return r.returncode == 0
def _run_executable(exe_path: Path, run_dir: Path) -> bool:
"""运行可执行文件, 返回是否成功"""
r = subprocess.run(
[str(exe_path)],
capture_output=True, text=True, timeout=15,
cwd=str(run_dir),
)
if r.returncode != 0:
print(f"[run] stderr: {r.stderr[:300]}")
print(f"[run] stdout: {r.stdout.strip()}")
return r.returncode == 0
# ── 测试用例 ──
@pytest.mark.skipif(not _check_cobc(), reason="cobc 未安装或不在 PATH 中")
def test_gcov_basic_collect(work_dir: Path) -> None:
"""全链路: 编译 → 运行 → collect_gcov → 验证 line_rate"""
# 1. 写入 COBOL 源文件
src = work_dir / "test-gcov.cbl"
src.write_text(SAMPLE_COBOL, encoding="utf-8")
# 2. 编译 (--coverage)
assert _compile_with_coverage(src, work_dir), "cobc --coverage 编译失败"
# 3. 确认 .gcno 已生成
gcno_files = list(work_dir.glob("*.gcno"))
assert len(gcno_files) > 0, "编译后未生成 .gcno 文件"
# 4. 运行程序 (生成 .gcda)
exe = work_dir / "test-gcov.exe"
assert _run_executable(exe, work_dir), "程序运行失败"
# 5. 确认 .gcda 已生成
gcda_files = list(work_dir.glob("*.gcda"))
assert len(gcda_files) > 0, "运行后未生成 .gcda 文件"
# 6. 调用 collect_gcov() 采集覆盖率
result = collect_gcov(cobol_src=src, work_dir=work_dir)
print(f"[gcov] collect_gcov returned: {result}")
# 7. 验证结果
assert result["available"] is True, f"覆盖率采集失败: {result.get('reason', 'unknown')}"
assert result["line_rate"] > 0, f"line_rate 应为正值, 实际: {result['line_rate']}"
assert result["total_lines"] > 0, f"total_lines 应为正值, 实际: {result['total_lines']}"
assert result["executed_lines"] > 0, f"executed_lines 应为正值, 实际: {result['executed_lines']}"
# 8. 验证分支覆盖 (IF 的两路应至少覆盖了一路)
assert result["line_rate"] <= 1.0, f"line_rate 不应超过 1.0"
print(f"[gcov] ✅ line_rate={result['line_rate']} ({result['executed_lines']}/{result['total_lines']})")
@pytest.mark.skipif(not _check_cobc(), reason="cobc 未安装或不在 PATH 中")
def test_gcov_no_gcda_graceful(work_dir: Path) -> None:
"""无 .gcda 文件时 collect_gcov 应优雅降级"""
src = work_dir / "test-gcov.cbl"
src.write_text(SAMPLE_COBOL, encoding="utf-8")
# 编译但不运行, 所以没有 .gcda
subprocess.run(
["cobc", "-x", "--coverage", str(src), "-o", str(work_dir / "test-gcov.exe")],
capture_output=True, text=True, timeout=30,
cwd=str(work_dir),
)
result = collect_gcov(cobol_src=src, work_dir=work_dir)
# 没有 .gcda 时应 graceful 返回 {available: False}
assert result["available"] is False
print(f"[gcov] 无 .gcda 降级正常: {result}")