当前位置: 首页 > 工具软件 > doctest > 使用案例 >

doctest 01 hello world

亢保赫
2023-12-01

目录结构

ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ tree -a
.
├── CMakeLists.txt
├── cm.py
├── cmake
│   └── khl_common_set_project_debug.cmake
├── include
│   └── khl_math
│       ├── calc.h
│       ├── khl_math.h
│       └── khl_math_config.h
├── src
│   ├── CMakeLists.txt
│   ├── khl_math
│   │   ├── CMakeLists.txt
│   │   └── calc.cpp
│   └── main
│       ├── CMakeLists.txt
│       └── main.cpp
├── test
│   ├── CMakeLists.txt
│   └── maintest.cpp
└── third
    └── doctest
        └── doctest.h

9 directories, 14 files
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ 

代码

c++

include/khl_math/calc.h

#ifndef _CALC_H_
#define _CALC_H_

#include "khl_math_config.h"

class DllExport Calc
{
public:
    Calc();
    ~Calc();

public:
    int add(int x, int y);
};

#endif // _CALC_H_

include/khl_math/khl_math.h

#ifndef  _KHL_MATH_H_
#define  _KHL_MATH_H_

#include "khl_math/calc.h"

// C/C++ 跨平台时预处理判断平台环境
// 参考: https://www.cnblogs.com/Forgenvueory/p/12757271.html
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
   #ifdef _WIN64
        #ifdef _DEBUG
            #pragma comment(lib,__FILE__"\\..\\..\\..\\lib\\khl_mathd.lib")
        #else
            #pragma comment(lib,__FILE__"\\..\\..\\..\\lib\\khl_math.lib")
        #endif
   #else
      //define something for Windows (32-bit only)
   #endif
#elif __APPLE__
    #include <TargetConditionals.h>
    #if TARGET_IPHONE_SIMULATOR
         // iOS Simulator
    #elif TARGET_OS_IPHONE
        // iOS device
    #elif TARGET_OS_MAC
        // Other kinds of Mac OS
    #else
    #   error "Unknown Apple platform"
    #endif
#elif __linux__
    // linux
#elif __unix__ // all unices not caught above
    // Unix
#elif defined(_POSIX_VERSION)
    // POSIX
#else
#   error "Unknown compiler"
#endif
#endif // _KHL_MATH_H_

include/khl_math/khl_math_config.h

#ifndef  _KHL_MATH_CONFIG_H_
#define  _KHL_MATH_CONFIG_H_

// C/C++ 跨平台时预处理判断平台环境
// 参考: https://www.cnblogs.com/Forgenvueory/p/12757271.html
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
   //define something for Windows (32-bit and 64-bit, this part is common)
   #ifdef _WIN64
      #define DllExport __declspec(dllexport)
   #else
      //define something for Windows (32-bit only)
   #endif
#elif __APPLE__
    #include <TargetConditionals.h>
    #if TARGET_IPHONE_SIMULATOR
         // iOS Simulator
    #elif TARGET_OS_IPHONE
        // iOS device
    #elif TARGET_OS_MAC
        // Other kinds of Mac OS
    #else
    #   error "Unknown Apple platform"
    #endif
#elif __linux__
    // linux
    #define DllExport
#elif __unix__ // all unices not caught above
    // Unix
#elif defined(_POSIX_VERSION)
    // POSIX
#else
#   error "Unknown compiler"
#endif
#endif // _KHL_MATH_CONFIG_H_

src/khl_math/calc.cpp

#include "khl_math/calc.h"


Calc::Calc()
{

}
Calc::~Calc()
{

}

int Calc::add(int x, int y)
{
    return x + y;
}

src/src/main.cpp

#include <iostream>
#include <memory>

#include "khl_math/khl_math.h"

int main()
{
    auto calc = std::make_unique<Calc>();
    std::cout << "1 + 2 = " << calc->add(1,2) << std::endl;
    std::cout << "Hello World!" << std::endl;
    return 0;
}

test/maintest.cpp

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest/doctest.h"

#include "khl_math/khl_math.h"

TEST_CASE("test khl_math")
{
    // MESSAGE("message - test khl_math calc add");
    int a = 1;
    INFO("info - test khl_math calc add ", a);
    
    auto calc = std::make_unique<Calc>();   
    CHECK(3 == calc->add(1,2));
}

CMakeLists.txt

CMakeLists.txt

# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.25)

project(hello CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(khl_common_set_project_debug)

# 编译模式是否为 debug
cmake_language(CALL khl_common_set_project_debug)

message(STATUS "====> project_debug : ${project_debug}")
message(STATUS "====> CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}")

# 设置 debug 库后缀
if(${project_debug})
    set(CMAKE_DEBUG_POSTFIX d)
endif()

# 消除警告  warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
# 参考: https://blog.csdn.net/five_east_west/article/details/125382251
if(${CMAKE_HOST_WIN32})
    add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
    add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
endif()

set(khl_math_lib_name khl_math${CMAKE_DEBUG_POSTFIX})

# 添加预处理器定义, 主要用于 windows
if(${project_debug})
    add_compile_definitions(_DEBUG)
endif()

# windows 平台
# 把 .dll 和 .lib 复制到 lib 目录
function(copy_dll_to_lib dll_name)
    if(${CMAKE_HOST_WIN32})
        set(dll_full_name ${CMAKE_SHARED_LIBRARY_PREFIX}${dll_name}${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
        set(dll_lib_name ${CMAKE_SHARED_LIBRARY_PREFIX}${dll_name}${CMAKE_DEBUG_POSTFIX}.lib)
        add_custom_command(TARGET ${dll_name} POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/build/src/${dll_name}/${CMAKE_BUILD_TYPE}/${dll_full_name} ${CMAKE_SOURCE_DIR}/lib/${dll_full_name})
        add_custom_command(TARGET ${dll_name} POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/build/src/${dll_name}/${CMAKE_BUILD_TYPE}/${dll_lib_name} ${CMAKE_SOURCE_DIR}/lib/${dll_lib_name})
    endif()
endfunction()

# windows 平台
# 把 .dll 复制到 bin 目录
function(copy_dll_to_exe dll_name)
    if(${CMAKE_HOST_WIN32})
        set(dll_full_name ${CMAKE_SHARED_LIBRARY_PREFIX}${dll_name}${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
        add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/build/src/${dll_name}/${CMAKE_BUILD_TYPE}/${dll_full_name} ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE})
    endif()
endfunction()

add_subdirectory(src)

# 添加测试项目所在目录
add_subdirectory(test)
# 必须添加这两行, 而且必须在顶层 CMakeLists.txt 添加
enable_testing()
add_test(NAME hello_test COMMAND hello_test)

src/CMakeLists.txt

add_subdirectory(main)
add_subdirectory(khl_math)

src/khl_math/CMakeLists.txt

# 头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. CALC_SRCS)

# 设置生成目录
if(${CMAKE_HOST_LINUX})
    message(STATUS "====> linux lib dir")
    set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib)
endif()


# 生成动态库, 默认生成的是静态库
add_library(${khl_math_lib_name} SHARED ${CALC_SRCS})

# 指定动态库版本
# VERSION 动态库版本
# SOVERSION API版本
set_target_properties(${khl_math_lib_name} PROPERTIES VERSION 1.0 SOVERSION 1)

cmake_language(CALL copy_dll_to_lib ${khl_math_lib_name})

src/main/CMakeLists.txt

# 头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. MAIN_SRCS)

# 可执行文件目录
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)

# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${MAIN_SRCS})

if(${CMAKE_HOST_LINUX})
    target_link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/lib)
    target_link_libraries(${PROJECT_NAME} ${khl_math_lib_name})
endif()

add_dependencies(${PROJECT_NAME} ${khl_math_lib_name})

cmake_language(CALL copy_dll_to_exe ${khl_math_lib_name})

src/test/CMakeLists.txt

# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(hello_test CXX)

# 指定 c++ 14
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(khl_common_set_project_debug)

message(STATUS "====> project_debug : ${project_debug}")
message(STATUS "====> CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}")

# 设置 debug 库后缀
if(${project_debug})
    set(CMAKE_DEBUG_POSTFIX d)
endif()

# 消除警告  warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
# 参考: https://blog.csdn.net/five_east_west/article/details/125382251
if(${CMAKE_HOST_WIN32})
    add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
    add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
endif()

# 添加预处理器定义, 主要用于 windows
if(${project_debug})
    add_compile_definitions(_DEBUG)
endif()

include_directories(${CMAKE_SOURCE_DIR}/third)

include_directories(${CMAKE_SOURCE_DIR}/include)

aux_source_directory(. TEST_SRCS)

set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)

add_executable(${PROJECT_NAME} ${TEST_SRCS})

if(${CMAKE_HOST_LINUX})
    target_link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/lib)
    target_link_libraries(${PROJECT_NAME} ${khl_math_lib_name})
endif()

cm.py

避免重复繁琐的命令行操作, 默认是构建并运行测试

ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ python3 cm.py --help
usage: cm.py [-h] {build,rebuild,run,test,clean} ...

positional arguments:
  {build,rebuild,run,test,clean}
    build               构建
    rebuild             重新构建
    run                 运行
    test                测试
    clean               清理

options:
  -h, --help            show this help message and exit
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ 

# -*- coding: utf-8 -*-
import argparse
import os
import platform
import os.path

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

KEY_CM_ACTION = 'cm_action'
ARG_PREFIX = '--'

SUB_COMMAND_BUILD = 'build'

SUB_COMMAND_RE_BUILD = 'rebuild'

SUB_COMMAND_RUN = 'run'

SUB_COMMAND_TEST = 'test'

SUB_COMMAND_CLEAN = 'clean'

def register_build_args():
    build_parsers = subparsers.add_parser(SUB_COMMAND_BUILD, help='构建')
    build_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_BUILD)

def register_re_build_args():
    rebuild_parsers = subparsers.add_parser(SUB_COMMAND_RE_BUILD, help='重新构建')
    rebuild_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_RE_BUILD)

def register_run_args():
    run_parsers = subparsers.add_parser(SUB_COMMAND_RUN, help='运行')
    run_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_RUN)

def register_test_args():
    test_parsers = subparsers.add_parser(SUB_COMMAND_TEST, help='测试')
    test_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_TEST)

def register_clean_args():
    test_parsers = subparsers.add_parser(SUB_COMMAND_CLEAN, help='清理')
    test_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_CLEAN)

def is_windows():
    return 'Windows' == platform.system()

def get_build_dir():
    return os.getcwd() + os.path.sep + 'build'

def get_bin_dir():
    return os.getcwd() + os.path.sep + 'bin'

def get_lib_dir():
    return os.getcwd() + os.path.sep + 'lib'


def execute_build():
    if is_windows():
        os.system('cmake -S . -B build -DCMAKE_CONFIGURATION_TYPES=Release && cmake --build build --config=release')
    else:
        os.system('cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build --config=release')

def execute_re_build():
    execute_clean()
    if is_windows():
        os.system('cmake -S . -B build -DCMAKE_CONFIGURATION_TYPES=Release && cmake --build build --config=release')
    else:
        os.system('cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build --config=release')

def execute_run():
    execute_build()
    if is_windows():
        os.system(".\\bin\\Release\\hello.exe")
    else:
        os.system('./bin/hello')

def execute_test():
    execute_build()
    if is_windows():
        os.system(".\\bin\\Release\\hello_test.exe")
    else:
        os.system('./bin/hello_test')

def execute_clean():
    if is_windows():
        if os.path.exists(get_build_dir()):
            os.system('rd /q/s build')
        if os.path.exists(get_bin_dir()):
            os.system('rd /q/s bin')
        if os.path.exists(get_lib_dir()):
            os.system('rd /q/s lib')
    else:
        if os.path.exists(get_build_dir()):
            os.system('rm -rf build')
        if os.path.exists(get_bin_dir()):
            os.system('rm -rf bin')
        if os.path.exists(get_lib_dir()):
            os.system('rm -rf lib')


if __name__ == '__main__':
    register_build_args()
    register_re_build_args()
    register_run_args()
    register_test_args()
    register_clean_args()

    args = parser.parse_args()
    if 0 == len(args.__dict__):
        execute_test()
    else:
        if SUB_COMMAND_BUILD == args.__dict__[KEY_CM_ACTION]:
            execute_build()
        if SUB_COMMAND_RE_BUILD == args.__dict__[KEY_CM_ACTION]:
            execute_re_build()
        if SUB_COMMAND_RUN == args.__dict__[KEY_CM_ACTION]:
            execute_run()
        if SUB_COMMAND_TEST == args.__dict__[KEY_CM_ACTION]:
            execute_test()
        if SUB_COMMAND_CLEAN == args.__dict__[KEY_CM_ACTION]:
            execute_clean()

windows 验证

F:\2023\code\cpp\vscode\doctest\doctest-01>cm.py
-- Building for: Visual Studio 17 2022
-- Selecting Windows SDK version 10.0.22000.0 to target Windows 10.0.19045.
-- The CXX compiler identification is MSVC 19.34.31937.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/program/microsoft/vs2022/community/VC/Tools/MSVC/14.34.31933/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- ====> khl_common_set_project_debug : 判断是否为 debug 模式
-- ====> khl_common_set_project_debug : 编译模式: release
-- ====> project_debug : 0
-- ====> CMAKE_BUILD_TYPE : Release
-- ====> project_debug : 0
-- ====> CMAKE_BUILD_TYPE : Release
-- Configuring done
-- Generating done
-- Build files have been written to: F:/2023/code/cpp/vscode/doctest/doctest-01/build
MSBuild version 17.4.1+9a89d02ff for .NET Framework
  Checking Build System
  Building Custom Rule F:/2023/code/cpp/vscode/doctest/doctest-01/src/khl_math/CMakeLists.txt
  calc.cpp
    正在创建库 F:/2023/code/cpp/vscode/doctest/doctest-01/build/src/khl_math/Release/khl_math.lib 和对象 F:/2023/code/cpp/vscode/doctest/doctest-01/build/src/khl_math/Release/khl_math.exp
  khl_math.vcxproj -> F:\2023\code\cpp\vscode\doctest\doctest-01\build\src\khl_math\Release\khl_math.dll
  Building Custom Rule F:/2023/code/cpp/vscode/doctest/doctest-01/src/main/CMakeLists.txt
  main.cpp
    正在创建库 F:/2023/code/cpp/vscode/doctest/doctest-01/bin/Release/hello.lib 和对象 F:/2023/code/cpp/vscode/doctest/doctest-01/bin/Release/hello.exp
  hello.vcxproj -> F:\2023\code\cpp\vscode\doctest\doctest-01\bin\Release\hello.exe
  Building Custom Rule F:/2023/code/cpp/vscode/doctest/doctest-01/test/CMakeLists.txt
  maintest.cpp
    正在创建库 F:/2023/code/cpp/vscode/doctest/doctest-01/bin/Release/hello_test.lib 和对象 F:/2023/code/cpp/vscode/doctest/doctest-01/bin/Release/hello_test.exp
  hello_test.vcxproj -> F:\2023\code\cpp\vscode\doctest\doctest-01\bin\Release\hello_test.exe
  Building Custom Rule F:/2023/code/cpp/vscode/doctest/doctest-01/CMakeLists.txt
[doctest] doctest version is "2.4.9"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases: 2 | 2 passed | 0 failed | 0 skipped
[doctest] assertions: 2 | 2 passed | 0 failed |
[doctest] Status: SUCCESS!

F:\2023\code\cpp\vscode\doctest\doctest-01>rd /q/s build

F:\2023\code\cpp\vscode\doctest\doctest-01>tree /f
Folder PATH listing for volume dox
Volume serial number is 34D2-6BE8
F:.
│   cm.py
│   CMakeLists.txt
│
├───bin
│   └───Release
│           hello.exe
│           hello.exp
│           hello.lib
│           hello_test.exe
│           hello_test.exp
│           hello_test.lib
│           khl_math.dll
│
├───cmake
│       khl_common_set_project_debug.cmake
│
├───include
│   └───khl_math
│           calc.h
│           khl_math.h
│           khl_math_config.h
│
├───lib
│       khl_math.dll
│       khl_math.lib
│
├───src
│   │   CMakeLists.txt
│   │
│   ├───khl_math
│   │       calc.cpp
│   │       CMakeLists.txt
│   │
│   └───main
│           CMakeLists.txt
│           main.cpp
│
├───test
│       CMakeLists.txt
│       maintest.cpp
│
└───third
    └───doctest
            doctest.h


F:\2023\code\cpp\vscode\doctest\doctest-01>

linux 验证

ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ python3 cm.py test
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- ====> khl_common_set_project_debug : 判断是否为 debug 模式
-- ====> khl_common_set_project_debug : 编译模式: release
-- ====> project_debug : 0
-- ====> CMAKE_BUILD_TYPE : Release
-- ====> linux lib dir
-- ====> project_debug : 0
-- ====> CMAKE_BUILD_TYPE : Release
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ubuntu/code/cpp/doctest/doctest-01/build
[ 16%] Building CXX object src/khl_math/CMakeFiles/khl_math.dir/calc.cpp.o
[ 33%] Linking CXX shared library /home/ubuntu/code/cpp/doctest/doctest-01/lib/libkhl_math.so
[ 33%] Built target khl_math
[ 50%] Building CXX object src/main/CMakeFiles/hello.dir/main.cpp.o
[ 66%] Linking CXX executable /home/ubuntu/code/cpp/doctest/doctest-01/bin/hello
[ 66%] Built target hello
[ 83%] Building CXX object test/CMakeFiles/hello_test.dir/maintest.cpp.o
[100%] Linking CXX executable /home/ubuntu/code/cpp/doctest/doctest-01/bin/hello_test
[100%] Built target hello_test
[doctest] doctest version is "2.4.9"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases: 2 | 2 passed | 0 failed | 0 skipped
[doctest] assertions: 2 | 2 passed | 0 failed |
[doctest] Status: SUCCESS!
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ rm -rf build/
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ tree -a
.
├── CMakeLists.txt
├── bin
│   ├── hello
│   └── hello_test
├── cm.py
├── cmake
│   └── khl_common_set_project_debug.cmake
├── include
│   └── khl_math
│       ├── calc.h
│       ├── khl_math.h
│       └── khl_math_config.h
├── lib
│   ├── libkhl_math.so -> libkhl_math.so.1
│   ├── libkhl_math.so.1 -> libkhl_math.so.1.0
│   └── libkhl_math.so.1.0
├── src
│   ├── CMakeLists.txt
│   ├── khl_math
│   │   ├── CMakeLists.txt
│   │   └── calc.cpp
│   └── main
│       ├── CMakeLists.txt
│       └── main.cpp
├── test
│   ├── CMakeLists.txt
│   └── maintest.cpp
└── third
    └── doctest
        └── doctest.h

11 directories, 19 files
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ 

上述操作有什么问题

  1. 所有的测试逻辑都写在一个文件
  2. 没有日志
  3. 没有测试报告

多个文件

可以有多个文件引入doctest.h, 只要保证只有一个文件有 #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN即可.

日志

 类似资料:

相关阅读

相关文章

相关问答