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

如何在Boost 1.63中程序化创建BOOST_AUTO_TEST_CASE以单独测试脚本?

适配Boost 1.63的单脚本独立测试实现方案

问题背景

我有一个测试项目,需读取并解析多个不同文件,触发C++库的不同模块后生成验证对象。当前通过单个BOOST_AUTO_TEST_CASE可批量运行所有脚本且正常工作,但需实现每个脚本单独运行的功能。此前尝试的AI方案在Visual Studio和Boost环境下无法正常工作,同时必须保持与Boost 1.63版本的兼容性,以适配无法升级软件版本的客户。

当前代码实现:

#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>

#include "Helpers/MyTestHelper.h"

#include "Utils/ExceptionHandler.h"

namespace MyProjecNamespace
{
/// Test Fixture
struct MyProjectScriptFixture
{
    boost::filesystem::path testDir_; ///< File path to the Project scripts directory

    MyProjectScriptFixture()
      : testDir_(boost::filesystem::system_complete("Scripts"))
   {
      SetupFloatingPointEnvironment();
   }

   ~MyProjectScriptFixture() {}
};

BOOST_FIXTURE_TEST_SUITE(MyProjectScriptTests, MyProjectScriptFixture)

BOOST_AUTO_TEST_CASE(RunMyProject_TestSuite)
{
   boost::filesystem::recursive_directory_iterator it(testDir_);
   boost::filesystem::recursive_directory_iterator end;

   while (it != end)
   {
      if (boost::filesystem::is_regular_file(it->path()))
      {
         InputProcessor inputProcessor(FileParsingOptions{ false, true, false, true, false });

         inputProcessor.DisableLogging();
         inputProcessor.ProcessFileInput(it->path().generic_string());

         std::pair<bool, std::string> result = inputProcessor.GetVerificationStatus();

         BOOST_CHECK_MESSAGE(result.first, it->path().filename().string() + " - " + result.second);
      }
      ++it;
   }
}

BOOST_AUTO_TEST_SUITE_END()
}

原AI方案失效原因

GPT给出的方案试图在运行时动态创建BOOST_AUTO_TEST_CASE,但Boost.Test的测试用例是编译期注册的,BOOST_AUTO_TEST_CASE是预处理宏,只能在编译阶段展开。运行时通过函数调用生成测试用例的方式完全不符合Boost.Test的工作机制,因此在VS和Boost环境下必然失效。

可行解决方案

方案1:编译期自动生成独立测试用例(适合文件列表稳定场景)

编写脚本遍历Scripts目录,自动生成每个文件对应的BOOST_AUTO_TEST_CASE代码,使每个脚本对应一个独立测试用例,可在VS测试资源管理器中单独选择运行。

自动生成代码的Python脚本

import os
import re

def generate_test_cases(script_dir, output_file):
    with open(output_file, 'w') as f:
        # 写入固定的头文件和Fixture定义
        f.write("""#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>

#include "Helpers/MyTestHelper.h"
#include "Utils/ExceptionHandler.h"

namespace MyProjecNamespace
{
struct MyProjectScriptFixture
{
    boost::filesystem::path testDir_;

    MyProjectScriptFixture()
      : testDir_(boost::filesystem::system_complete("Scripts"))
    {
        SetupFloatingPointEnvironment();
    }

    ~MyProjectScriptFixture() {}
};

BOOST_FIXTURE_TEST_SUITE(MyProjectScriptTests, MyProjectScriptFixture)
""")

        # 遍历脚本目录生成测试用例
        for root, dirs, files in os.walk(script_dir):
            for file in files:
                rel_path = os.path.relpath(os.path.join(root, file), script_dir)
                # 将路径中的特殊字符替换为下划线,生成合法的C++标识符
                test_name = "Test_" + re.sub(r'[\\/.]', '_', rel_path)
                # 写入单个测试用例代码
                f.write(f"""
BOOST_AUTO_TEST_CASE({test_name})
{{
    boost::filesystem::path filePath = testDir_ / "{rel_path.replace('\\', '/')}";
    InputProcessor inputProcessor(FileParsingOptions{{ false, true, false, true, false }});
    inputProcessor.DisableLogging();
    inputProcessor.ProcessFileInput(filePath.generic_string());

    std::pair<bool, std::string> result = inputProcessor.GetVerificationStatus();
    BOOST_CHECK_MESSAGE(result.first, filePath.filename().string() + " - " + result.second);
}}
""")

        # 写入测试套件结尾
        f.write("""
BOOST_AUTO_TEST_SUITE_END()
}
""")

if __name__ == "__main__":
    generate_test_cases("Scripts", "GeneratedScriptTests.cpp")

使用方式

  1. 将该脚本加入项目的预构建事件,确保每次构建前自动生成GeneratedScriptTests.cpp文件
  2. 将生成的GeneratedScriptTests.cpp添加到项目中编译
  3. 构建完成后,VS测试资源管理器中会显示每个脚本对应的测试用例,可单独选择运行

方案2:命令行参数指定单个脚本(适合文件动态变化场景)

修改原有测试代码,支持通过命令行参数指定单个脚本路径,无需预生成代码即可实现单独运行。

修改后的代码:

#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include <vector>
#include <string>

#include "Helpers/MyTestHelper.h"
#include "Utils/ExceptionHandler.h"

namespace MyProjecNamespace
{
struct MyProjectScriptFixture
{
    boost::filesystem::path testDir_;
    std::vector<boost::filesystem::path> targetFiles_;

    MyProjectScriptFixture()
      : testDir_(boost::filesystem::system_complete("Scripts"))
    {
        SetupFloatingPointEnvironment();

        // 获取Boost.Test的命令行参数
        auto& args = boost::unit_test::framework::master_test_suite().argv;
        int argc = boost::unit_test::framework::master_test_suite().argc;

        // 解析命令行参数中的目标文件
        if (argc > 1)
        {
            for (int i = 1; i < argc; ++i)
            {
                boost::filesystem::path filePath(args[i]);
                // 优先检查绝对路径是否存在
                if (boost::filesystem::exists(filePath))
                {
                    targetFiles_.push_back(filePath);
                }
                else
                {
                    // 尝试相对于测试目录查找文件
                    boost::filesystem::path relativePath = testDir_ / filePath;
                    if (boost::filesystem::exists(relativePath))
                    {
                        targetFiles_.push_back(relativePath);
                    }
                }
            }
        }

        // 未指定参数时,默认遍历所有脚本文件
        if (targetFiles_.empty())
        {
            boost::filesystem::recursive_directory_iterator it(testDir_);
            boost::filesystem::recursive_directory_iterator end;
            while (it != end)
            {
                if (boost::filesystem::is_regular_file(it->path()))
                {
                    targetFiles_.push_back(it->path());
                }
                ++it;
            }
        }
    }

    ~MyProjectScriptFixture() {}
};

BOOST_FIXTURE_TEST_SUITE(MyProjectScriptTests, MyProjectScriptFixture)

BOOST_AUTO_TEST_CASE(RunMyProject_TestSuite)
{
    for (const auto& filePath : targetFiles_)
    {
        InputProcessor inputProcessor(FileParsingOptions{ false, true, false, true, false });
        inputProcessor.DisableLogging();
        inputProcessor.ProcessFileInput(filePath.generic_string());

        std::pair<bool, std::string> result = inputProcessor.GetVerificationStatus();
        BOOST_CHECK_MESSAGE(result.first, filePath.filename().string() + " - " + result.second);
    }
}

BOOST_AUTO_TEST_SUITE_END()
}

使用方式

  • 批量运行:直接运行测试程序,无需额外参数,自动遍历所有脚本
  • 单独运行单个脚本:
    1. 在VS中:右键测试项目→属性→调试→命令行参数,输入脚本的相对路径(如script1.txt)或绝对路径
    2. 命令行中:执行TestProject.exe script1.txt或TestProject.exe "subdir/script2.txt"

方案对比

方案优点缺点
编译期生成测试用例VS测试资源管理器中可直观看到每个脚本对应的测试用例,支持图形化选择单独运行需要维护生成脚本,文件变动后需重新生成代码
命令行参数指定无需预生成代码,文件变动无需修改测试代码无法在VS测试资源管理器中直接选择单个脚本,需手动设置命令行参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:38:09