You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CMake合并多个测试用例实现单次运行结果统计

问题描述

我用CMake构建并测试C语言代码,已创建多个独立测试用例,但每次单独运行测试时,每个测试都会显示“100% 1/1”的结果。我希望将这些测试合并为一次运行,最终显示汇总统计,比如“100% 4/4”(全部通过)或“75% tests passed, 1 tests failed out of 4”(存在失败)。

当前代码

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(my_project)

set(CMAKE_C_STANDARD 11)

add_executable(my_project main.c)

enable_testing()

add_test(NAME build_test COMMAND ${CMAKE_COMMAND} --build .)

add_test(NAME run_test COMMAND my_project)
set_tests_properties(run_test PROPERTIES DEPENDS build_test)

add_test(NAME output_test COMMAND my_project 3)
set_tests_properties(output_test PROPERTIES PASS_REGULAR_EXPRESSION "Hello, World!\nHello, World!\nHello, World!")

add_test(NAME output_test2 COMMAND my_project 5)
set_tests_properties(output_test2 PROPERTIES PASS_REGULAR_EXPRESSION "Hello, World!\nHello, World!\nHello, World!\nHello, World!\nHello, World!\n")

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int n = atoi(argv[1]);
    for(int i = 0; i < n; i++) {
        printf("Hello, World!\n");
    }
    return 0;
}

当前测试输出示例

[ctest]     Start 1: build_test
[ctest] 1/1 Test #1: build_test .......................   Passed    0.55 sec
[ctest] 
[ctest] 100% tests passed, 0 tests failed out of 1

期望输出示例

全部通过时

[ctest]     Start 1: combined_test
[ctest] 4/4 Test #1: combined_test ...................   Passed    0.55 sec
[ctest] 
[ctest] 100% tests passed, 0 tests failed out of 4

存在失败时

[ctest]     Start 1: combined_test
[ctest] 4/4 Test #1: combined_test ...................   Passed    0.55 sec
[ctest] 
[ctest] 75% tests passed, 1 tests failed out of 4
解决方案

将多个测试逻辑整合到自定义脚本中,让CTest执行该脚本,脚本内部统计所有测试用例的结果并返回整体状态。

步骤1:创建测试脚本run_all_tests.sh

#!/bin/bash

total_tests=4
passed_tests=0

# 测试1:构建项目
echo "Running build_test..."
cmake --build .
if [ $? -eq 0 ]; then
    passed_tests=$((passed_tests + 1))
    echo "build_test: PASSED"
else
    echo "build_test: FAILED"
fi

# 测试2:运行程序(修复无参数崩溃问题,默认传1)
echo "Running run_test..."
./my_project 1
if [ $? -eq 0 ]; then
    passed_tests=$((passed_tests + 1))
    echo "run_test: PASSED"
else
    echo "run_test: FAILED"
fi

# 测试3:输出3次Hello World
echo "Running output_test..."
output=$("./my_project" 3)
expected="Hello, World!
Hello, World!
Hello, World!"
if [ "$output" == "$expected" ]; then
    passed_tests=$((passed_tests + 1))
    echo "output_test: PASSED"
else
    echo "output_test: FAILED"
fi

# 测试4:输出5次Hello World
echo "Running output_test2..."
output=$("./my_project" 5)
expected="Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!"
if [ "$output" == "$expected" ]; then
    passed_tests=$((passed_tests + 1))
    echo "output_test2: PASSED"
else
    echo "output_test2: FAILED"
fi

# 输出汇总统计
echo ""
echo "$passed_tests/$total_tests tests passed"
[ $passed_tests -eq $total_tests ] && exit 0 || exit 1

步骤2:修改CMakeLists.txt

替换原有的多个add_test配置,改为执行上述脚本:

cmake_minimum_required(VERSION 3.16)
project(my_project)

set(CMAKE_C_STANDARD 11)

add_executable(my_project main.c)

enable_testing()

# 添加合并后的测试
add_test(NAME combined_test COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/run_all_tests.sh)

# 确保脚本可执行
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/run_all_tests.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
     FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
                      GROUP_READ GROUP_EXECUTE
                      WORLD_READ WORLD_EXECUTE)

步骤3:修复main.c无参数崩溃问题

原代码在无参数时访问argv[1]会触发未定义行为,修改为:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int n = 1;  // 设置默认值
    if (argc > 1) {
        n = atoi(argv[1]);
    }
    for(int i = 0; i < n; i++) {
        printf("Hello, World!\n");
    }
    return 0;
}
效果说明

运行ctest时,会执行combined_test任务,脚本内部依次运行4个测试用例,输出每个测试的结果后展示汇总统计。CTest会根据脚本的退出码判断整体测试是否通过,同时你可以在控制台清晰看到总测试数及通过率。

内容的提问来源于stack exchange,提问作者MorpKnight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:57:19