Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions tests/gen-ut-summary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: GPL-3.0-or-later

"""Generate ut-summary.json from gtest XML reports and lcov coverage data.

Usage:
Called from shell test scripts. Reads environment variables:
- projectdir: project root directory
- builddir: build directory name (relative to projectdir)
- reportdir: report output directory name (relative to projectdir)

Optional overrides (take precedence over defaults):
- GTEST_XML_DIR: directory containing gtest XML reports
- COVERAGE_INFO: path to lcov .info file for coverage parsing

Output: {projectdir}/{reportdir}/ut-summary.json
"""

import json
import xml.etree.ElementTree as ET
import glob
import os
import subprocess
import re
import sys


def parse_gtest_xml(xml_dir):
"""Parse Google Test / JUnit XML output and return (total, passed, failed)."""
total = passed = failed = 0
for xml_file in sorted(glob.glob(os.path.join(xml_dir, "*.xml"))):
try:
root = ET.parse(xml_file).getroot()
# JUnit format uses <testsuites> as root with aggregated counts
# gtest XML uses <testsuites> or <testsuite> as root
t = int(root.get("tests", 0))
f_count = int(root.get("failures", 0))
err_count = int(root.get("errors", 0))
total += t
failed += f_count + err_count
passed += t - f_count - err_count
except Exception as e:
print(f"Warning: failed to parse {xml_file}: {e}", file=sys.stderr)
return total, passed, failed


def parse_lcov_summary(coverage_info):
"""Parse lcov --summary output and return coverage dict."""
result = {}
if not os.path.exists(coverage_info):
print(f"Warning: coverage info file not found: {coverage_info}", file=sys.stderr)
return result

lcov_out = subprocess.run(
["lcov", "--summary", coverage_info, "--rc", "lcov_branch_coverage=1"],
capture_output=True, text=True
)
summary_text = lcov_out.stdout + lcov_out.stderr

# Parse lines: "lines......: XX.X% (NNN of MMMM lines)"
m_lines = re.search(r'lines.*?:\s*([\d.]+)%\s*\((\d+)\s+of\s+(\d+)\s+\w+\)', summary_text)
if m_lines:
pct, hit, total = m_lines.groups()
result["line_coverage"] = {
"total": int(total),
"passed": int(hit),
"failed": int(total) - int(hit),
"coverage": f"{float(pct):.2f}%"
}

# Parse functions: "functions..: XX.X% (NNN of MMMM functions)"
m_func = re.search(r'functions.*?:\s*([\d.]+)%\s*\((\d+)\s+of\s+(\d+)\s+\w+\)', summary_text)
if m_func:
pct, hit, total = m_func.groups()
result["function_coverage"] = {
"total": int(total),
"passed": int(hit),
"failed": int(total) - int(hit),
"coverage": f"{float(pct):.2f}%"
}

return result


def main():
projectdir = os.environ.get("projectdir")
builddir = os.environ.get("builddir")
reportdir = os.environ.get("reportdir")

if not all([projectdir, builddir, reportdir]):
print("Error: environment variables projectdir, builddir, reportdir are required", file=sys.stderr)
sys.exit(1)

# Resolve paths (env overrides take precedence)
gtest_dir = os.environ.get("GTEST_XML_DIR",
os.path.join(projectdir, builddir, "report"))
coverage_info = os.environ.get("COVERAGE_INFO",
os.path.join(projectdir, builddir, "coverage.info"))

# --- Test case counts from gtest XML ---
total, passed, failed = parse_gtest_xml(gtest_dir)

result = {
"test_cases": {
"total": total,
"passed": passed,
"failed": failed
}
}

# --- Coverage from lcov --summary ---
coverage_data = parse_lcov_summary(coverage_info)
result.update(coverage_data)

# --- Write output ---
output_path = os.path.join(projectdir, reportdir, "ut-summary.json")
os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, "w") as f:
json.dump(result, f, indent=2)

print(json.dumps(result, indent=2))


if __name__ == "__main__":
main()
29 changes: 24 additions & 5 deletions tests/test-prj-running.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#!/bin/bash
builddir=build
reportdir=build-ut
# SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: GPL-3.0-or-later

export builddir=build
export reportdir=build-ut
scriptdir=$(cd $(dirname $0); pwd)
export projectdir=$(cd "$scriptdir/.."; pwd)

rm -r $builddir
rm -r ../$builddir
rm -r $reportdir
Expand All @@ -10,11 +17,18 @@ mkdir ../$reportdir
cd ../$builddir
#编译
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_SAFETYTEST_ARG="CMAKE_SAFETYTEST_ARG_ON" ..
make -j8
make -j$(nproc)
#生成asan日志和ut测试xml结果
export ASAN_OPTIONS=abort_on_error=0:detect_leaks=0
export UBSAN_OPTIONS=halt_on_error=0
./tests/deepin-editor-test --gtest_output=xml:./report/report_deepin-editor.xml

# 运行测试并生成 gtest XML 报告
GTEST_XML_DIR="$projectdir/$builddir/report"
mkdir -p "$GTEST_XML_DIR"
set +e
./tests/deepin-editor-test --gtest_output="xml:$GTEST_XML_DIR/report_deepin-editor.xml"
test_exit_code=$?
set -e

workdir=$(cd ../$(dirname $0)/$builddir; pwd)

Expand All @@ -34,4 +48,9 @@ cp -r html ../$reportdir/
cp -r report ../$reportdir/
cp asan*.log* ../$reportdir/asan_deepin-editor.log 2>/dev/null || true

exit 0
# 生成摘要 JSON
echo "==> Generating summary JSON: $projectdir/$reportdir/ut-summary.json"

python3 "$scriptdir/gen-ut-summary.py"

exit $test_exit_code
Loading