<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 4.1 創建一個簡單的單元測試 **NOTE**:*此示例代碼可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-04/recipe-01 中找到,包含一個C++的示例。該示例在CMake 3.5版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。* CTest是CMake的測試工具,本示例中,我們將使用CTest進行單元測試。為了保持對CMake/CTest的關注,我們的測試代碼會盡可能的簡單。計劃是編寫和測試能夠對整數求和的代碼,示例代碼只會對整數進行累加,不處理浮點數。就像年輕的卡爾?弗里德里希?高斯(Carl Friedrich Gauss),被他的老師測試從1到100求和所有自然數一樣,我們將要求代碼做同樣的事情。為了說明CMake沒有對實際測試的語言進行任何限制,我們不僅使用C++可執行文件測試代碼,還使用Python腳本和shell腳本作為測試代碼。為了簡單起見,我們將不使用任何測試庫來實現,但是我們將在 后面的示例中介紹C++測試框架。 ## 準備工作 代碼示例由三個文件組成。實現源文件`sum_integs.cpp`對整數向量進行求和,并返回累加結果: ```c++ #include "sum_integers.hpp" #include <vector> int sum_integers(const std::vector<int> integers) { auto sum = 0; for (auto i : integers) { sum += i; } return sum; } ``` 這個示例是否是優雅的實現并不重要,接口以`sum_integers`的形式導出。接口在` sum_integers.hpp `文件中聲明,詳情如下: ```c++ #pragma once #include <vector> int sum_integers(const std::vector<int> integers); ``` 最后,main函數在`main.cpp`中定義,從`argv[]`中收集命令行參數,將它們轉換成整數向量,調用`sum_integers`函數,并將結果打印到輸出中: ```c++ #include "sum_integers.hpp" #include <iostream> #include <string> #include <vector> // we assume all arguments are integers and we sum them up // for simplicity we do not verify the type of arguments int main(int argc, char *argv[]) { std::vector<int> integers; for (auto i = 1; i < argc; i++) { integers.push_back(std::stoi(argv[i])); } auto sum = sum_integers(integers); std::cout << sum << std::endl; } ``` 測試這段代碼使用C++實現(`test.cpp`),Bash shell腳本實現(`test.sh`)和Python腳本實現(`test.py`),只要實現可以返回一個零或非零值,從而CMake可以解釋為成功或失敗。 C++例子(`test.cpp`)中,我們通過調用`sum_integers`來驗證1 + 2 + 3 + 4 + 5 = 15: ```c++ #include "sum_integers.hpp" #include <vector> int main() { auto integers = {1, 2, 3, 4, 5}; if (sum_integers(integers) == 15) { return 0; } else { return 1; } } ``` Bash shell腳本調用可執行文件: ```shell #!/usr/bin/env bash EXECUTABLE=$1 OUTPUT=$($EXECUTABLE 1 2 3 4) if [ "$OUTPUT" = "10" ] then exit 0 else exit 1 fi ``` 此外,Python腳本調用可執行文件(使用`--executable`命令行參數傳遞),并使用`--short`命令行參數執行: ```python import subprocess import argparse # test script expects the executable as argument parser = argparse.ArgumentParser() parser.add_argument('--executable', help='full path to executable') parser.add_argument('--short', default=False, action='store_true', help='run a shorter test') args = parser.parse_args() def execute_cpp_code(integers): result = subprocess.check_output([args.executable] + integers) return int(result) if args.short: # we collect [1, 2, ..., 100] as a list of strings result = execute_cpp_code([str(i) for i in range(1, 101)]) assert result == 5050, 'summing up to 100 failed' else: # we collect [1, 2, ..., 1000] as a list of strings result = execute_cpp_code([str(i) for i in range(1, 1001)]) assert result == 500500, 'summing up to 1000 failed' ``` ## 具體實施 現在,我們將逐步描述如何為項目設置測試: 1. 對于這個例子,我們需要C++11支持,可用的Python解釋器,以及Bash shell: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(recipe-01 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(PythonInterp REQUIRED) find_program(BASH_EXECUTABLE NAMES bash REQUIRED) ``` 2. 然后,定義庫及主要可執行文件的依賴關系,以及測試可執行文件: ```cmake # example library add_library(sum_integers sum_integers.cpp) # main code add_executable(sum_up main.cpp) target_link_libraries(sum_up sum_integers) # testing binary add_executable(cpp_test test.cpp) target_link_libraries(cpp_test sum_integers) ``` 3. 最后,打開測試功能并定義四個測試。最后兩個測試, 調用相同的Python腳本,先沒有任何命令行參數,再使用`--short`: ```cmake enable_testing() add_test( NAME bash_test COMMAND ${BASH_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test.sh $<TARGET_FILE:sum_up> ) add_test( NAME cpp_test COMMAND $<TARGET_FILE:cpp_test> ) add_test( NAME python_test_long COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test.py --executable $<TARGET_FILE:sum_up> ) add_test( NAME python_test_short COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test.py --short --executable $<TARGET_FILE:sum_up> ) ``` 4. 現在,我們已經準備好配置和構建代碼。先手動進行測試: ```shell $ mkdir -p build $ cd build $ cmake .. $ cmake --build . $ ./sum_up 1 2 3 4 5 15 ``` 5. 然后,我們可以用`ctest`運行測試集: ```shell $ ctest Test project /home/user/cmake-recipes/chapter-04/recipe-01/cxx-example/build Start 1: bash_test 1/4 Test #1: bash_test ........................ Passed 0.01 sec Start 2: cpp_test 2/4 Test #2: cpp_test ......................... Passed 0.00 sec Start 3: python_test_long 3/4 Test #3: python_test_long ................. Passed 0.06 sec Start 4: python_test_short 4/4 Test #4: python_test_short ................ Passed 0.05 sec 100% tests passed, 0 tests failed out of 4 Total Test time (real) = 0.12 sec ``` 6. 還應該嘗試中斷實現,以驗證測試集是否能捕捉到更改。 ## 工作原理 這里的兩個關鍵命令: * `enable_testing()`,測試這個目錄和所有子文件夾(因為我們把它放在主`CMakeLists.txt`)。 * `add_test()`,定義了一個新的測試,并設置測試名稱和運行命令。 ```cmake add_test( NAME cpp_test COMMAND $<TARGET_FILE:cpp_test> ) ``` 上面的例子中,使用了生成器表達式:`$<TARGET_FILE:cpp_test>`。生成器表達式,是在生成**構建系統生成時**的表達式。我們將在第5章第9節中詳細地描述生成器表達式。此時,我們可以聲明` $<TARGET_FILE:cpp_test>`變量,將使用`cpp_test`可執行目標的完整路徑進行替換。 生成器表達式在測試時非常方便,因為不必顯式地將可執行程序的位置和名稱,可以硬編碼到測試中。以一種可移植的方式實現這一點非常麻煩,因為可執行文件和可執行后綴(例如,Windows上是`.exe`后綴)的位置在不同的操作系統、構建類型和生成器之間可能有所不同。使用生成器表達式,我們不必顯式地了解位置和名稱。 也可以將參數傳遞給要運行的`test`命令,例如: ```cmake add_test( NAME python_test_short COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test.py --short --executable $<TARGET_FILE:sum_up> ) ``` 這個例子中,我們按順序運行測試,并展示如何縮短總測試時間并行執行測試(第8節),執行測試用例的子集(第9節)。這里,可以自定義測試命令,可以以任何編程語言運行測試集。CTest關心的是,通過命令的返回碼測試用例是否通過。CTest遵循的標準約定是,返回零意味著成功,非零返回意味著失敗。可以返回零或非零的腳本,都可以做測試用例。 既然知道了如何定義和執行測試,那么了解如何診斷測試失敗也很重要。為此,我們可以在代碼中引入一個bug,讓所有測試都失敗: ```shell Start 1: bash_test 1/4 Test #1: bash_test ........................***Failed 0.01 sec Start 2: cpp_test 2/4 Test #2: cpp_test .........................***Failed 0.00 sec Start 3: python_test_long 3/4 Test #3: python_test_long .................***Failed 0.06 sec Start 4: python_test_short 4/4 Test #4: python_test_short ................***Failed 0.06 sec 0% tests passed, 4 tests failed out of 4 Total Test time (real) = 0.13 sec The following tests FAILED: 1 - bash_test (Failed) 2 - cpp_test (Failed) 3 - python_test_long (Failed) 4 - python_test_short (Failed) Errors while running CTest ``` 如果我們想了解更多,可以查看文件`test/Temporary/lasttestsfailure.log`。這個文件包含測試命令的完整輸出,并且在分析階段,要查看的第一個地方。使用以下CLI開關,可以從CTest獲得更詳細的測試輸出: * `--output-on-failure`:將測試程序生成的任何內容打印到屏幕上,以免測試失敗。 * `-v`:將啟用測試的詳細輸出。 * `-vv`:啟用更詳細的輸出。 CTest提供了一個非常方快捷的方式,可以重新運行以前失敗的測試;要使用的CLI開關是`--rerun-failed`,在調試期間非常有用。 ## 更多信息 考慮以下定義: ```cmake add_test( NAME python_test_long COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test.py --executable $<TARGET_FILE:sum_up> ) ``` 前面的定義可以通過顯式指定腳本運行的`WORKING_DIRECTORY`重新表達,如下: ```cmake add_test( NAME python_test_long COMMAND ${PYTHON_EXECUTABLE} test.py --executable $<TARGET_FILE:sum_up> WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) ``` 測試名稱可以包含`/`字符,按名稱組織相關測試也很有用,例如: ```cmake add_test( NAME python/long COMMAND ${PYTHON_EXECUTABLE} test.py --executable $<TARGET_FILE:sum_up> WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) ``` 有時候,我們需要為測試腳本設置環境變量。這可以通過`set_tests_properties`實現: ```cmake set_tests_properties(python_test PROPERTIES ENVIRONMENT ACCOUNT_MODULE_PATH=${CMAKE_CURRENT_SOURCE_DIR} ACCOUNT_HEADER_FILE=${CMAKE_CURRENT_SOURCE_DIR}/account/account.h ACCOUNT_LIBRARY_FILE=$<TARGET_FILE:account> ) ``` 這種方法在不同的平臺上并不總可行,CMake提供了解決這個問題的方法。下面的代碼片段與上面給出的代碼片段相同,在執行實際的Python測試腳本之前,通過`CMAKE_COMMAND`調用CMake來預先設置環境變量: ```cmake add_test( NAME python_test COMMAND ${CMAKE_COMMAND} -E env ACCOUNT_MODULE_PATH=${CMAKE_CURRENT_SOURCE_DIR} ACCOUNT_HEADER_FILE=${CMAKE_CURRENT_SOURCE_DIR}/account/account.h ACCOUNT_LIBRARY_FILE=$<TARGET_FILE:account> ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/account/test.py ) ``` 同樣,要注意使用生成器表達式` $<TARGET_FILE:account> `來傳遞庫文件的位置。 我們已經使用`ctest`命令執行測試,CMake還將為生成器創建目標(Unix Makefile生成器為`make test`,Ninja工具為`ninja test`,或者Visual Studio為`RUN_TESTS`)。這意味著,還有另一種(幾乎)可移植的方法來運行測試: ```shell $ cmake --build . --target test ``` 不幸的是,當使用Visual Studio生成器時,我們需要使用`RUN_TESTS`來代替: ```shell $ cmake --build . --target RUN_TESTS ``` **NOTE**:*`ctest`提供了豐富的命令行參數。其中一些內容將在以后的示例中探討。要獲得完整的列表,需要使用`ctest --help`來查看。命令`cmake --help-manual ctest`會將向屏幕輸出完整的ctest手冊。*
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看