- Published on
Googletest Unit Testing in C++ Projects
- Authors
- Name
- light-city
Googletest Unit Testing in C++ Projects
Table of Contents
1. Integrating Googletest Unit Testing in CLion
Googletest - Google Testing and Mocking Framework
Source code download link:
Googletest contains two modules, namely gtest and gmock, which need to be compiled separately from source. After compilation, copy the includes
folder and .so
files to the specified location below.
Then, create an ext
directory in the project, divided into two parts:
- First part: includes
Includes the include files for gmock and gtest, corresponding to the gcc -I
parameter, indicating the path to the header files ending with .h
.
- Second part: libs
Contains the libs files for gmock and gtest, corresponding to the gcc -L
parameter, indicating the path to the library files containing .so
or .dll
dynamic or static linking libraries.
├── ext
│ ├── includes
│ │ ├── gmock
│ │ └── gtest
│ └── libs
│ ├── gmock
│ └── gtest
After configuring the above local project path, configure it in CmakeLists.txt:
# ext
set(BASE_INCLUDES ext/includes)
set(BASE_LIBS ext/libs)
# googletest
set(GTEST_INCLUDE_DIR ${BASE_INCLUDES}/gtest/include)
set(GMOCK_INCLUDE_DIR ${BASE_INCLUDES}/gmock/include)
set(GTEST_LINK_DIR ${BASE_LIBS}/gtest/lib/)
set(GMOCK_LINK_DIR ${BASE_LIBS}/gmock/lib/)
# Where to find the header files equivalent to gcc/clang's -I parameter
include_directories(${GTEST_INCLUDE_DIR})
include_directories(${GMOCK_INCLUDE_DIR})
# Where to find the library files .so .dll .dylib equivalent to gcc's -L parameter
link_directories(${GTEST_LINK_DIR})
link_directories(${GMOCK_LINK_DIR})
Then link libraries for each test.
For example, if there is a test file named l1.cpp
, configure it in CmakeLists.txt as follows:
add_executable(l1 l1.cpp)
target_link_libraries(l1 gtest gtest_main)
2. Introduction to Googletest: Hello World
int main(int argc, char* argv[])
{
// Accept command line arguments
testing::InitGoogleTest(&argc, argv);
vector<int> x={1,2,3,5};
// Using EXPECT_EQ
for (int i = 0; i < x.size(); ++i)
{
EXPECT_EQ(x[i], 1) << "Vectors x and y differ at index " << i;
}
RUN_ALL_TESTS();
return 0;
}
For example, the above is a complete example. Every time it runs:
testing::InitGoogleTest(&argc, argv);
And then use:
RUN_ALL_TESTS();
To run all tests, with assertions written for each test.
Let's see the running effect:
l1.cpp:113: Failure
Expected equality of these values:
x[i]
Which is: 2
1
Vectors x and y differ at index 1
l1.cpp:113: Failure
Expected equality of these values:
x[i]
Which is: 3
1
Vectors x and y differ at index 2
l1.cpp:113: Failure
Expected equality of these values:
x[i]
Which is: 5
1
Vectors x and y differ at index 3
[==========] Running 0 tests from 0 test cases.
[==========] 0 tests from 0 test cases ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 0 tests, listed below:
0 FAILED TESTS
2. Introduction to Googletest Assertions
Regarding assertions, Google has wrapped a series of macros EXPECT
and ASSERT
, where the difference between the EXPECT
series and the ASSERT
series is:
EXPECT
: When failed, the case continues to execute.ASSERT
: When failed, it returns directly within the current function, and the statements afterASSERT
in the current function will not be executed.
For example:
TEST(ASSERTTest, ASSERT_VS_EXPECT)
{
ASSERT_TRUE(10<2); // ASSERT fails, returns directly within the current function, subsequent statements do not execute
ASSERT_FALSE(10<2);
EXPECT_EQ(6, Foo(310, 18));
}
Each Test is a macro, the underlying source code for Test is as follows:
# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
Corresponding to the test case name and the test name.
In the above code, 10<2
is False, and ASSERT_TRUE
is used. All content after this Test will not be executed. If changed to EXPECT_TRUE
, it will run normally!
Boolean Check
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_TRUE( condition) ; | EXPECT_TRUE( condition) ; | condition is true |
ASSERT_FALSE( condition) ; | EXPECT_FALSE( condition) ; | condition is false |
Numeric Data Check
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_EQ( expected, actual); | EXPECT_EQ( expected, actual); | expected == actual |
ASSERT_NE( val1, val2); | EXPECT_NE( val1, val2); | val1 != val2 |
ASSERT_LT( val1, val2); | EXPECT_LT( val1, val2); | val1 < val2 |
ASSERT_LE( val1, val2); | EXPECT_LE( val1, val2); | val1 <= val2 |
ASSERT_GT( val1, val2); | EXPECT_GT( val1, val2); |
| val1 >
val2 | | ASSERT_GE(
val1,
val2);
| EXPECT_GE(
val1,
val2);
| val1 >=
val2 |
String Check
TEST(StringCmpTest, Demo)
{
char* pszCoderZh = "CoderZh";
wchar_t* wszCoderZh = L"CoderZh";
std::string strCoderZh = "CoderZh";
std::wstring wstrCoderZh = L"CoderZh";
EXPECT_STREQ("CoderZh", pszCoderZh);
EXPECT_STREQ(L"CoderZh", wszCoderZh);
EXPECT_STRNE("CnBlogs", pszCoderZh);
EXPECT_STRNE(L"CnBlogs", wszCoderZh);
EXPECT_STRCASEEQ("coderzh", pszCoderZh);
//EXPECT_STRCASEEQ(L"coderzh", wszCoderZh); Not supported
EXPECT_STREQ("CoderZh", strCoderZh.c_str());
EXPECT_STREQ(L"CoderZh", wstrCoderZh.c_str());
}
Where STREQ
and STRNE
support both char*
and wchar_t*
types, STRCASEEQ
and STRCASENE
only accept char*
.
Display Success or Failure
To directly return success: SUCCEED();
To return failure:
Fatal assertion | Nonfatal assertion |
---|---|
FAIL(); | ADD_FAILURE(); |
// Return success or failure
TEST(ExplicitTest, Demo)
{
ADD_FAILURE() << "This line fails Sorry"; // None Fatal Asserton,continues execution.
//FAIL(); // Fatal Assertion,does not execute the following statements in this test case.
EXPECT_TRUE(1==2)<<"1==2 failed!"; // To verify whether the statements after failure are executed
SUCCEED();
}
Exception Check
There are three types:
EXPECT_NO_THROW(statement);
: No exception thrown.
EXPECT_ANY_THROW(statement);
: Any type of exception thrown.
EXPECT_THROW(statement, exception_type);
: Specific type of exception thrown.
TEST(ExceptionTest,et) {
// Any type of exception thrown
EXPECT_ANY_THROW(10/0); //Expected: 10/0 throws an exception.
// Specific type of exception thrown
EXPECT_THROW(1/0,int); //Expected: 1/0 throws an exception of type int.
}
Predicate Assertions
When checking whether a function returns TRUE or FALSE, it is useful to output the parameters passed in, to facilitate tracking in case of failure.
For example:
// Predicate Assertion
bool MN(int m, int n)
{
return m>n;
}
// When checking whether a function returns TRUE or FALSE, it is useful to output the parameters passed in, to facilitate tracking in case of failure.
TEST(PredicateAssertionTest, Demo)
{
int m = 5, n = 6;
EXPECT_PRED2(MN, m, n); //Provide only <= 5 parameters, parameters should correspond to the MN function
}
EXPECT_PRED2(pred2, val1, val2);
is similar to ASSERT. PRED2 can go up to PRED5.
Supports up to 5 parameters.
Floating-Point Check
EXPECT_FLOAT_EQ(expected, actual)
and EXPECT_DOUBLE_EQ(expected, actual)
Similar to ASSERT.
For comparing two close numbers:
EXPECT_NEAR(val1, val2, abs_error);
Similar to ASSERT.
For example:
// Floating-Point
TEST(FloatDoubleTest,Demo) {
ASSERT_DOUBLE_EQ(1.1,1.1);
EXPECT_FLOAT_EQ(1.2,4.0);
EXPECT_NEAR(1.234,1.888,0.9);
// EXPECT_PRED_FORMAT2(testing::FloatLE, val1, val2);
// EXPECT_PRED_FORMAT2(testing::DoubleLE, val1, val2);
EXPECT_PRED_FORMAT2(testing::FloatLE,1,0); // LE means less than or equal to, i.e., value1 <= value2
EXPECT_PRED_FORMAT2(testing::DoubleLE,0.1,0.2);
}
Type Check
// Type Check
template <typename T>
class Tt{
public:
void foo() {
testing::StaticAssertTypeEq<bool, T>(); // No error if consistent with the call below, otherwise error
}
};
TEST(TypeAssertionTest, Demo)
{
Tt<bool> tt;
tt.foo();
}
Learning reference from: https://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html