- Published on
C++ Project: Googletest Unit Testing
- Authors
- Name
- light-city
C++ Project: Googletest Unit Testing
Table of Contents
1. Integrating Googletest Unit Testing into Clion
Googletest - Google Testing and Mocking Framework
Source code download link:
Googletest contains two modules, gtest and gmock, which need to be compiled separately. After compilation, copy the includes
folder and .so
files to the specified locations under the following path.
Then create a directory named ext
in the project, which is divided into two parts:
The first part:
includes
Contains include files for gmock and gtest, corresponding to the
-I
parameter in gcc, which is the header file path, containing header files ending with.h
.The second part:
libs
Contains libs files for gmock and gtest, corresponding to the
-L
parameter in gcc, which is the library file path, containing.so
or.dll
dynamic or static linking libraries.
├── ext
│ ├── includes
│ │ ├── gmock
│ │ └── gtest
│ └── libs
│ ├── gmock
│ └── gtest
Once the local project path configuration is set up, 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 header files, equivalent to the -I parameter in gcc/clang
include_directories(${GTEST_INCLUDE_DIR})
include_directories(${GMOCK_INCLUDE_DIR})
# Where to find library files, .so .dll .dylib, equivalent to the -L parameter in gcc
link_directories(${GTEST_LINK_DIR})
link_directories(${GMOCK_LINK_DIR})
Then, link the appropriate libraries for each test.
For example, if there's 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. HelloWorld with Googletest
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. Each time you run:
testing::InitGoogleTest(&argc, argv);
And then use:
RUN_ALL_TESTS();
to run all tests. Refer to the assertions below for each test.
Let's see the output:
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
3. Introduction to Googletest Assertions
Google has encapsulated a series of macros EXPECT
and ASSERT
, where the difference between the EXPECT
series and ASSERT
series is:
EXPECT
: continues execution if failed.ASSERT
: returns directly in the current function if failed, and the statements afterASSERT
will not be executed.
For example:
TEST(ASSERTTest, ASSERT_VS_EXPECT)
{
ASSERT_TRUE(10<2); // Directly returns in the current function if failed, and the statements below will not be executed
ASSERT_FALSE(10<2);
EXPECT_EQ(6, Foo(310, 18));
}
Each test is a macro, and the underlying source code of 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 test name.
The assertion types are as follows:
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_TRUE( condition) ; | EXPECT_TRUE( condition) ; | condition is true |
ASSERT_FALSE( condition) ; | EXPECT_FALSE( condition) ; | condition is false |
For numeric data checks:
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 |
For string checks:
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, while STRCASEEQ
and STRCASENE
only accept char*
.
For explicit success or failure:
Success: SUCCEED();
Failure:
Fatal assertion | Nonfatal assertion |
---|---|
FAIL(); | ADD_FAILURE(); |
// Success or Failure
TEST(ExplicitTest, Demo)
{
ADD_FAILURE() << "This line fails Sorry"; // None Fatal Asserton,continues execution.
//FAIL(); // Fatal Assertion, does not continue execution of this test.
EXPECT_TRUE(1==2)<<"1==2 failed!"; // To verify if the statements after failure are executed
SUCCEED();
}
For exception checks:
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) {
// No 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.
}
For Predicate Assertions:
When checking if a function returns TRUE
or FALSE
, it's helpful to output the parameters passed in, for better tracking after failure.
For example:
// Predicate Assertions
bool MN(int m, int n)
{
return m>n;
}
// Checking if a function returns TRUE or FALSE, helpful to output the parameters passed in, for better tracking after failure
TEST(PredicateAssertionTest, Demo)
{
int m = 5, n = 6;
EXPECT_PRED2(MN, m, n); // Only provides <=5 parameters, parameters should correspond to function MN
}
EXPECT_PRED2(pred2, val1, val2);
Similar to ASSERT
. PRED2
can go up to PRED5
.
Supports up to 5 parameters.
For floating point checks:
EXPECT_FLOAT_EQ(expected, actual)
and EXPECT_DOUBLE_EQ(expected, actual)
Similar to ASSERT
.
For comparing two closely-related numbers:
EXPECT_NEAR(val1, val2, abs_error);
Similar to ASSERT
.
For type checks:
// Type checks
template <typename T>
class Tt{
public:
void foo() {
testing::StaticAssertTypeEq<bool, T>(); // No error if consistent with the following call, otherwise error
}
};
TEST(TypeAssertionTest, Demo)
{
Tt<bool> tt;
tt.foo();
}
Learning reference: https://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html