本指南將向您展示如何通過Google的測試框架使用CMake和單元測試來設置新的C ++項目。 通過此設置,您可以立即開始使用C ++進行測試驅動的開發。 弄清楚如何將gtest添加到現有項目並開始在舊的(現有)代碼庫上進行TDD也很簡單。
環境:win10 子系統linux ubuntu18.04
確保已經安裝了cmake(3.10以上),g++,gcc等基本環境。
最後的效果圖:
從github上將 google test 源碼clone下來
git clone https://github.com/google/googletest/
gtest 項目裏面包含了CMakeLists.txt,所以集成到自己的項目裏面是比較簡單的(如果你懂cmake的話,如果不懂的話就按照本指南做吧。
文件結構
IndexProject
├── CMakeLists.txt
├── build
├── lib
│ └── googletest
├── src
│ ├── CMakeLists.txt
│ ├── Formula.cpp
│ ├── Formula.h
│ └── main.cpp
└── tst
├── CMakeLists.txt
├── Formula-test.cpp
└── main.cpp
下面這個命令是創建這個目錄結構
mkdir -p IndexProject/{build,lib,src,tst}
將clone下來的gooletest 文件夾放到項目的lib文件夾下。
大部分的個人的簡單項目用以上目錄結構應該都沒問題,所以這個相當於一個模板吧,供自己以後以及其它菜鳥參考。最好的方式當然是學習CMake,然後自己隨心所欲想怎麼搞怎麼搞,可以CMake想搞明白還挺花時間的,對於時間緊迫的人這個模板是個不錯的選擇。
CMakeLists.txt
生成target有兩種方式,一種直接將文件名一個個列出來,這樣的好處是不需要編譯不必要的文件。
add_executable(ExampleProject main.cpp file1.cpp file1.h)
還有一種是將所有的文件全編譯然後生成執行文件,這樣的好處是添加文件後不需要修改CMakeLists.txt就可以直接運行。
file(GLOB_RECURSE SOURCES LIST_DIRECTORIES true *.h *.cpp)
根目錄下的CMakeLists.txt
# cmake version
cmake_minimum_required(VERSION 3.10)
# project name
project(IndexProject)
#採用c++14標準
set(CMAKE_CXX_STANDARD 14)
include_directories(src)
add_subdirectory(src)
add_subdirectory(tst)
add_subdirectory(lib/googletest)
這裏的include_directories(src)是爲了讓src下的頭文件全局可見。
src 目錄下的CMakeLists.txt
#設置 BINARY 爲項目名IndexProject
set(BINARY ${CMAKE_PROJECT_NAME})
# 1
# add_executable(ExampleProject main.cpp file1.cpp file1.h)
# 2
file(GLOB_RECURSE SOURCES LIST_DIRECTORIES true *.h *.cpp)
set(SOURCES ${SOURCES})
add_executable(${BINARY}_run ${SOURCES})
# 爲了讓單元測試的時候src下的代碼能被作爲靜態鏈接庫使用
add_library(${BINARY}_lib STATIC ${SOURCES})
tst 目錄下的CMakeLists.txt
set(BINARY ${CMAKE_PROJECT_NAME}_tst)
file(GLOB_RECURSE TEST_SOURCES LIST_DIRECTORIES false *.h *.cpp)
set(SOURCES ${TEST_SOURCES})
add_executable(${BINARY} ${TEST_SOURCES})
add_test(NAME ${BINARY} COMMAND ${BINARY})
# 鏈接src生成的lib庫和gtest庫
target_link_libraries(${BINARY} PUBLIC ${CMAKE_PROJECT_NAME}_lib gtest)
添加源代碼
src/main.cpp
:
#include <iostream>
#include "Formula.h"
int main() {
std::cout << "Bla: " << Formula::bla(2) << std::endl;
return 0;
}
src/Formula.h
#ifndef EXAMPLEPROJECT_FORMULA_H
#define EXAMPLEPROJECT_FORMULA_H
class Formula {
public:
static int bla(int arg1);
};
#endif //EXAMPLEPROJECT_FORMULA_H
src/Formula.cpp
:
#include "Formula.h"
int Formula::bla(int arg1) {
return arg1 * 2;
}
添加測試代碼
tst/main.cpp
#include "gtest/gtest.h"
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
上面那個文件會執行所有tst目錄下的測試文件的所有測試用例,這裏只添加一個。
tst/Formula-test.cpp
#include "gtest/gtest.h"
#include "Formula.h"
TEST(blaTest, test1) {
//arrange
//act
//assert
EXPECT_EQ (Formula::bla (0), 0); //通過
EXPECT_EQ (Formula::bla (2), 4); //通過
EXPECT_EQ (Formula::bla (4), 6); //不通過
}
編譯
cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug
輸出
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc - works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PythonInterp: /usr/bin/python3.6 (found version "3.6.9")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /d/code/IndexProject/build
然後使用 make 編譯生成我們需要的東西,可以使用
make all
生成所有的。
輸出
Scanning dependencies of target IndexProject_lib
[ 5%] Building CXX object src/CMakeFiles/IndexProject_lib.dir/Formula.cpp.o
[ 11%] Building CXX object src/CMakeFiles/IndexProject_lib.dir/main.cpp.o
[ 17%] Linking CXX static library libIndexProject_lib.a
[ 17%] Built target IndexProject_lib
Scanning dependencies of target IndexProject_run
[ 23%] Building CXX object src/CMakeFiles/IndexProject_run.dir/Formula.cpp.o
[ 29%] Building CXX object src/CMakeFiles/IndexProject_run.dir/main.cpp.o
[ 35%] Linking CXX executable IndexProject_run
[ 35%] Built target IndexProject_run
Scanning dependencies of target gtest
[ 41%] Building CXX object lib/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 47%] Linking CXX static library ../../libgtestd.a
[ 47%] Built target gtest
Scanning dependencies of target IndexProject_tst
[ 52%] Building CXX object tst/CMakeFiles/IndexProject_tst.dir/Formula-test.cpp.o
[ 58%] Building CXX object tst/CMakeFiles/IndexProject_tst.dir/main.cpp.o
[ 64%] Linking CXX executable IndexProject_tst
[ 64%] Built target IndexProject_tst
Scanning dependencies of target gmock
[ 70%] Building CXX object lib/googletest/googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
[ 76%] Linking CXX static library ../../libgmockd.a
[ 76%] Built target gmock
Scanning dependencies of target gmock_main
[ 82%] Building CXX object lib/googletest/googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o
[ 88%] Linking CXX static library ../../libgmock_maind.a
[ 88%] Built target gmock_main
Scanning dependencies of target gtest_main
[ 94%] Building CXX object lib/googletest/googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[100%] Linking CXX static library ../../libgtest_maind.a
[100%] Built target gtest_main
這裏還生成了gmock,這是googletest下面的另一個項目,如果不想生成它們,也可以使用以下命令生成我們想要的:
make IndexProject_tst;make IndexProject_run
[ 12%] Building CXX object src/CMakeFiles/IndexProject_lib.dir/Formula.cpp.o
[ 25%] Building CXX object src/CMakeFiles/IndexProject_lib.dir/main.cpp.o
[ 37%] Linking CXX static library libIndexProject_lib.a
[ 37%] Built target IndexProject_lib
[ 50%] Building CXX object lib/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 62%] Linking CXX static library ../../libgtestd.a
[ 62%] Built target gtest
[ 75%] Building CXX object tst/CMakeFiles/IndexProject_tst.dir/Formula-test.cpp.o
[ 87%] Building CXX object tst/CMakeFiles/IndexProject_tst.dir/main.cpp.o
[100%] Linking CXX executable IndexProject_tst
[100%] Built target IndexProject_tst
[ 33%] Building CXX object src/CMakeFiles/IndexProject_run.dir/Formula.cpp.o
[ 66%] Building CXX object src/CMakeFiles/IndexProject_run.dir/main.cpp.o
[100%] Linking CXX executable IndexProject_run
[100%] Built target IndexProject_run
找到我們生成的可執行文件
$ find . -executable -type f -name "IndexProject*"
./src/IndexProject_run
./tst/IndexProject_tst
執行
$ ./src/IndexProject_run;./tst/IndexProject_tst
Bla: 4
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from blaTest
[ RUN ] blaTest.test1
/d/code/IndexProject/tst/Formula-test.cpp:9: Failure
Expected equality of these values:
Formula::bla(4)
Which is: 8
6
[ FAILED ] blaTest.test1 (1 ms)
[----------] 1 test from blaTest (2 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (3 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] blaTest.test1
1 FAILED TEST
這篇指南主要參考一個國外的博客,如果想看原版內容,點擊這裏,找了好久才找到能看懂的博客,cmake看了大半天還是沒太搞明白,只能看懂這種傻瓜式的教程了哈哈。以上博客如果記載有錯漏之處請私信或者直接查看原文。本人也只是按照那個博客自己試了一遍。