Introduction
In the previous articleArticleWe learned how to use the gtest test firmware to complete the test.CodeAnd Test Data reuse, this section we will learn how to use the gtest value parameterization method to simplify function testing; Use the type parameterization method to simplify the test of the template class.
Value parameterization
Suppose we want to test the following functions:
//Determines whether N is a prime number.
BoolIsprime (IntN)
Suppose we want to write a test case that determines the result as false. Based on the assertions learned earlier and the usage of test (), we compile the test code as follows:
//Tests negative input.
Test (isprimetest, negative ){
Expect_false (isprime (-1));
Expect_false (isprime (-2));
Expect_false (isprime (-5));
Expect_false (isprime (-100));
Expect_false (isprime (int_min ));
}
Apparently, we copied and pasted the statement "expect_false (isprime (x)" five times, but when the tested data contains dozens of hundreds of times, the method of copying and pasting is weak. Next, let's take a look at the methods provided by gtest to solve this problem.
First, we add a class inherited from: Testing: testwithparam <t>, where T is the type of the tested data. For the above function isprimetest, add the following class:
ClassIsprimeparamtest:Public: Testing: testwithparam <Int>
{
};
In this class, we can compile the setup () and teardown () functions to complete data initialization and data cleanup respectively. We can also add class members and other class member functions for related usage, for more information, see the example of gtest project. Here we only test functions, and do not need to use setup () or other methods. isprimeparamtest is an empty class.
Then we need to use the macro test_p to compile the corresponding test code:
Test_p (isprimeparamtest, negative)
{
IntN = getparam ();
Expect_false (isprime (n ));
}
The getparam () method is used to obtain the specific value of the current parameter. Is this test code much simpler than the previous one ?!
Finally, we use instantiate_test_case_p () to inform gtest of all our tested parameters:
Instantiate_test_case_p (negativetest, isprimeparamtest, testing: values (-1,-2,-5,-100,Int_min));
The first parameter is the prefix of the test instance and can be obtained at will. The second parameter is the name of the test class. The third parameter indicates the tested parameter, test :: values indicates that parameters in parentheses are used. Run the test case and the result is as follows:
Running main () from gtest_main.cc
[=========] Running5 Tests from 1 Test Case .
[----------] Global test ENVI Set -Up.
[----------] 5 Tests from negativetest/isprimeparamtest
[ Run ] Negativetest/isprimeparamtest. Negative/ 0
[ OK ] Negativetest/isprimeparamtest. Negative/ 0 ( 0 MS)
[ Run ] Negativetest/isprimeparamtest. Negative/ 1
[ OK ] Negativetest/isprimeparamtest. Negative/ 1 ( 0 MS)
[ Run ] Negativetest/isprimeparamtest. Negative/ 2
[ OK ] Negativetest/isprimeparamtest. Negative/ 2 ( 0 MS)
[ Run ] Negativetest/isprimeparamtest. Negative/ 3
[ OK ] Negativetest/isprimeparamtest. Negative/ 3 ( 0 MS)
[ Run ] Negativetest/isprimeparamtest. Negative/ 4
[ OK ] Negativetest/isprimeparamtest. Negative/ 4 ( 0 MS)
[----------] 5 Tests from negativetest/isprimeparamtest ( 1 MS total)
[----------] Global test environment tear-down
[=========] 5 Tests from 1 Test Case Ran .( 1 MS total)
[Passed] 5 Tests.
The results show that each test instance is called prefix/test case name. The name of the test instance.
Type parameterization
Like listing tested values in the form of parameters, we can also list the tested types in the form of parameters, which greatly facilitates testing the template class. Gtest provides two different methods for writing test code: known test type and unknown test type, let's assume that we use two methods to test the following classes:
Template <typename E>//E is the element type.
ClassQueue {
Public:
Queue ();
VoidEnqueue (ConstE & element );
E * dequeue ();//Returns NULL if the queue is empty.
Size_t size ()Const;
...
};
Method 1: known tested types
For the preceding template queue, if we know that we need to test the int and Char Types before writing the test code, first we need to compile the queue factory method to generate the specific type:
Template <ClassT>
Queue <t> * createqueue ();
Template <>
Queue <Int> * Createqueue <Int> ()
{
Return NewQueue <Int>;
}
Template <>
Queue <Char> * Createqueue <Char> ()
{
Return NewQueue <Char>;
}
Then we need to write the test fixture class template ):
Template <ClassT>
ClassQueuetest:PublicTesting: Test
{
Protected:
Queuetest (): Queue (createqueue <t> ()){}
Virtual~ Queuetest () {Delete queue ;}
Queue <t> *ConstQueue;
};
We can see that the queuetest constructor uses the factory method to initialize the class member variable queue. Then we need to declare and register the type we want to test:
UsingTesting: types;
// The list of types we want to test.
Typedef types <Int,Char> Implementations;
Typed_test_case (queuetest, implementations );
Here we use a new macro: typed_test_case (testcasename, typelist). The first parameter is the test case name, and the second parameter is the type list. Finally, we use the typed_test macro to write the detection code:
//Check whether the queue size is 0 after the object is generated
Typed_test (queuetest, defaultconstructor ){
Expect_eq (0u,This-> Queue-> size ());
}
Compile and run the testProgramThe test results are as follows:
Running main () from gtest_main.cc
[=========] Running 2 Tests from 2 Test cases.
[----------] Global test environment Set -Up.
[----------]1 Test from queuetest/ 0 , Where Typeparam = Int
[Run] queuetest/ 0 . Defaultconstructor
[OK] queuetest/ 0 . Defaultconstructor ( 0 MS)
[----------] 1 Test from queuetest/ 0 ( 1 MS total)
[----------]1 Test from queuetest/ 1 , Where Typeparam = Char
[Run] queuetest/ 1 . Defaultconstructor
[OK] queuetest/ 1 . Defaultconstructor ( 0 MS)
[----------] 1 Test from queuetest/ 1 ( 0 MS total)
[----------] Global test environment tear-down
[=========] 2 Tests from 2 Test Cases ran .( 1 MS total)
[Passed] 2 Tests.
Method 2: unknown type
When writing test cases, we may not know which types of the queue class will be instantiated or tested. Is it impossible to write test cases ?! With peace of mind, gtest provides us with a method that allows us to write test cases first. The specific types to be tested can be supplemented later. This method is as follows:
Same as method 1, we need to use the factory method for generating queue and define the firmware template. The figure here is convenient and inherits the above queuetest template class.
Template <ClassT>
ClassQueuetest2:PublicQueuetest <t> {
};
Next, use the macro typed_test_case_p to declare the test case. The parameter is the name of the firmware template class.
Typed_test_case_p (queuetest2 );
Then we can use the macro typed_test_p to write the test case:
//Check whether the queue size is 0 after the object is generated
Typed_test_p (queuetest2, defaultconstructor ){
Expect_eq (0u,This-> Queue-> size ());
}
Compared with method 1, This method takes another step: register a test instance. The register_typed_test_case_p macro must be used here:
Register_typed_test_case_p (queuetest2, defaultconstructor );
Through the above basics, most of our unknown type test code has been compiled, but we do not have a real test instance, because we have not specified the test type. We usually write the above test code into a. h header file. Any code that wants to instantiate a specific type can # include this header file.
Suppose we want to test the int and Char Types, we can write the following code in A. CC file:
Typedef types <Int,Char> Implementations;
Instantiate_typed_test_case_p (queueint_char, queuetest2, implementations );
Similarly, we need to use types to list the tested types. Note that the listed types are listed after the test instance is written using typed_test_p.
Summary
In this section, we learned how to use the gtest value parameterization method to simplify function testing, and how to use known-type parameterization and unknown-type parameterization methods to simplify the testing of the template class. The gtest project provides an example of a custom class with both values and types. If you are interested, click here.
Reference: googletest Project
Google open-source C ++ unit testing framework-Google test series by coderzh