gpt4 book ai didi

unit-testing - CMake:如何对自己的 CMake 脚本宏/功能进行单元测试?

转载 作者:行者123 更新时间:2023-12-02 03:26:53 26 4
gpt4 key购买 nike

我已经围绕标准 CMake 命令编写了一些方便的包装器,并希望对此 CMake 脚本代码进行单元测试以确保其功能。

我已经取得了一些进展,但有两件事我希望得到帮助:

  • 是否有一些“官方”方式对您自己的 CMake 脚本代码进行单元测试?类似于运行 CMake 的特殊模式?我的目标是“白盒测试”(尽可能)。
  • 如何处理全局变量和变量范围问题?通过加载项目的缓存、配置测试 CMake 文件或通过 -D 命令行选项将其推送到测试中,将全局变量注入(inject)测试?变量范围的模拟/测试(缓存与非缓存、宏/函数/包含、引用传递的参数)?

  • 首先,我查看了/Tests 下的 CMake 源代码(我使用的是 CMake 版本 2.8.10),尤其是在 Tests/CMakeTests 下。有大量的品种可供发现,看起来其中很多都是专门针对单个测试用例的。

    所以我还研究了一些可用的 CMake 脚本库,例如 CMake++查看他们的解决方案,但是那些 - 当他们有单元测试时 - 很大程度上取决于他们自己的库函数。

    最佳答案

    这是我当前对我自己的 CMake 脚本代码进行单元测试的解决方案。

    假设使用 CMake 脚本处理模式是我最好的选择,并且我必须模拟在脚本模式下不可用的 CMake 命令,我 - 到目前为止 - 想出了以下内容。

    辅助函数

    利用我自己的全局属性,我编写了辅助函数来存储和比较函数调用:

    function(cmakemocks_clearlists _message_type)
    _get_property(_list_names GLOBAL PROPERTY MockLists)
    if (NOT "${_list_names}" STREQUAL "")
    foreach(_name IN ITEMS ${_list_names})
    _get_property(_list_values GLOBAL PROPERTY ${_name})
    if (NOT "${_list_values}" STREQUAL "")
    foreach(_value IN ITEMS ${_list_values})
    _message(${_message_type} "cmakemocks_clearlists(${_name}): \"${_value}\"")
    endforeach()
    endif()
    _set_property(GLOBAL PROPERTY ${_name} "")
    endforeach()
    endif()
    endfunction()
    function(cmakemocks_pushcall _name _str)
    _message("cmakemocks_pushcall(${_name}): \"${_str}\"")
    _set_property(GLOBAL APPEND PROPERTY MockLists "${_name}")
    _set_property(GLOBAL APPEND PROPERTY ${_name} "${_str}")
    endfunction()

    function(cmakemocks_popcall _name _str)
    _get_property(_list GLOBAL PROPERTY ${_name})
    set(_idx -1)
    list(FIND _list "${_str}" _idx)
    if ((NOT "${_list}" STREQUAL "") AND (NOT ${_idx} EQUAL -1))
    _message("cmakemocks_popcall(${_name}): \"${_str}\"")
    list(REMOVE_AT _list ${_idx})
    _set_property(GLOBAL PROPERTY ${_name} ${_list})
    else()
    _message(FATAL_ERROR "cmakemocks_popcall(${_name}): No \"${_str}\"")
    endif()
    endfunction()
    function(cmakemocks_expectcall _name _str)
    _message("cmakemocks_expectcall(${_name}): \"${_str}\" -> \"${ARGN}\"")
    _set_property(GLOBAL APPEND PROPERTY MockLists "${_name}")
    string(REPLACE ";" "|" _value_str "${ARGN}")
    _set_property(GLOBAL APPEND PROPERTY ${_name} "${_str} <<<${_value_str}>>>")
    endfunction()

    function(cmakemocks_getexpect _name _str _ret)
    if(NOT DEFINED ${_ret})
    _message(SEND_ERROR "cmakemocks_getexpect: ${_ret} given as _ret parameter in not a defined variable. Please specify a proper variable name as parameter.")
    endif()

    _message("cmakemocks_getexpect(${_name}): \"${_str}\"")
    _get_property(_list_values GLOBAL PROPERTY ${_name})

    set(_value_str "")

    foreach(_value IN ITEMS ${_list_values})
    set(_idx -1)
    string(FIND "${_value}" "${_str}" _idx)
    if ((NOT "${_value}" STREQUAL "") AND (NOT ${_idx} EQUAL -1))
    list(REMOVE_ITEM _list_values "${_value}")
    _set_property(GLOBAL PROPERTY ${_name} ${_list_values})

    string(FIND "${_value}" "<<<" _start)
    string(FIND "${_value}" ">>>" _end)
    math(EXPR _start "${_start} + 3")
    math(EXPR _len "${_end} - ${_start}")
    string(SUBSTRING "${_value}" ${_start} ${_len} _value_str)
    string(REPLACE "|" ";" _value_list "${_value_str}")
    set(${_ret} "${_value_list}" PARENT_SCOPE)
    break()
    endif()
    endforeach()
    endfunction()

    模型

    通过添加如下模型:
    macro(add_library)
    string(REPLACE ";" " " _str "${ARGN}")
    cmakemocks_pushcall(MockLibraries "${_str}")
    endmacro()

    macro(get_target_property _var)
    string(REPLACE ";" " " _str "${ARGN}")
    set(${_var} "[NULL]")
    cmakemocks_getexpect(MockGetTargetProperties "${_str}" ${_var})
    endmacro()

    测试

    我可以写一个这样的测试:

    MyUnitTests.cmake
    cmakemocks_expectcall(MockGetTargetProperties "MyLib TYPE" "STATIC_LIBRARY")
    my_add_library(MyLib "src/Test1.cc")
    cmakemocks_popcall(MockLibraries "MyLib src/Test1.cc")
    ...
    cmakemocks_clearlists(STATUS)

    并将其包含在我的 CMake 项目中:

    CMakeLists.txt
    add_test(
    NAME TestMyCMake
    COMMAND ${CMAKE_COMMAND} -P "MyUnitTests.cmake"
    )

    关于unit-testing - CMake:如何对自己的 CMake 脚本宏/功能进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29818725/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com