III,Cppunit Development Environment Settings |
|
After learning about the cppunit test environment, you must be ready to feel the feeling of test-driven development during your development process. However, you need to set up your development environment before using cppunit. |
|
1. lib and DLL of cppunit |
Cppunit provides two sets of framework libraries: static lib and dynamic DLL. |
|
Cppunit project: static lib |
Cppunit_dll project: Dynamic DLL and Lib |
|
In development, we can make a choice based on the actual situation. Go to the SRC folder and open cppunitlibraries. DSW. Compile the two projects respectively, and the output location is the Lib folder. |
Another project that requires attention is testrunner, which outputs a DLL and provides a GUI-based test environment, that is, one of the two test environments we mentioned earlier. We also need to compile this project, and the output location is also the Lib folder. |
To facilitate development, we copy the compiled lib and DLL (including the debug and release versions) to a folder created by ourselves (you can also skip this ), for example, F:/cppunit1.9.0/lib/. We also copy the include folder in the cppunit source code to our own include folder. Set the include path and Lib path in tools/options/directories/include files and library files of VC. Finally, do not forget to link the correct Lib in your project. |
|
2. Enable the rtti switch in your VC project. |
The specific location is Project Settings/C ++ language. |
|
3. Set environment variables for testrunner. dll |
Testrunner. dll provides a GUI-based testing environment. In order for our test program to call it correctly, testrunner. dll must be located in the path of your test program. However, the simplest method is to add the testrunner. dll path in the environment variable path of the operating system, which is the most convenient. |
|
IV,Your first TDD example |
|
Everything is ready. Now let's take a look at how to add the test code. As mentioned above, the smallest unit of cppunit is testcase, and multiple related testcase forms a testsuite. The simplest way to add test code is to use several macros that cppunit provides for us (of course there are other manual addition methods, but they all share the same path, you can refer to the Demo code in the cppunit header file ). These macros are: |
|
Cppunit_test_suite () to create a testsuite |
Cppunit_test () add testcase |
Cppunit_test_suite_end () ends creating testsuite |
Cppunit_test_suite_named_registration () Add a testsuite to a specified testfactoryregistry Factory |
|
If you are interested, you can go to helpermacros. h to check the macro statements. This article will not detail them here. |
|
1. a class that adds two integers |
Suppose we want to implement a class, and the class name is temporarily used as cplus. Its function is mainly to implement the addition of two numbers (a more simple class, should this be tested? It doesn't matter, we just know how to add the test code to test it, so the simpler the better ). Assume that the method to implement the addition of this class is: |
|
int Add(int nNum1, int nNum2); |
|
OK. Let's write the code for testing this method first. TDD writes the test code first, and then the product code (cplus! The test code written first often cannot be run or compiled. Our goal is to write the product code after writing the test code so that the code can be compiled and then restructured. This is what Kent Beck calls "red/green/refactor" (Do you still remember the status bar of the GUI-based test environment ?). Therefore, the above class name and method should be in your mind, but also your idea. |
|
2. Create a project for the test code in VC |
Generally, the test code and the tested object are in different projects. In this way, your product code will not be contaminated by the test code ". |
In this example, a GUI-based test environment is created. In VC, we create a project based on the dialog box. Don't forget to link the correct Lib. In this example, we use static cppunit Lib. Because we want this project to display an interface like Figure 2 after running, we need to block the original dialog box in the app instance () and replace it with the cppunit GUI. |
|
Cppunit: mfcui: testrunner runner; runner. addtest (plustest: Suite (); // Add a test runner. run (); // show UI/* ccplustestdlg DLG; m_pmainwnd = & DLG; int nresponse = DLG. domodal (); If (nresponse = idok) {// todo: Place code here to handle when the dialog is // dismissed with OK} else if (nresponse = idcancel) {// todo: Place code here to handle when the dialog is // dismissed with cancel }*/ |
|
As mentioned above, the dialog box like Figure 2 is output by testrunner, which is why we set the environment variable for the path of testrunner. dll. |
Note: plustest: Suite () returns a pointer to cppunit: test. This pointer is the starting point of the test. Cppunit: testfactoryregistry: getregistry () returns the testfactoryregistry factory based on the testsuite name, and then calls maketest () in the factory to assemble the testsuite. This is a recursive call, A tree-like test structure will be created. |
|
namespace PlusTest { CppUnit::Test* suite() { CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(plusSuiteName()); return registry.makeTest(); } } |
|
In addition, do not add the header file: |
#include "CPlusTestSuite.h" #include <cppunit/ui/mfc/TestRunner.h> #include <cppunit/extensions/TestFactoryRegistry.h> |
|
3. Add a class to the project named cplustestcase |
Cplustestcase inherits from cppunit: testcase. The Code is as follows: |
|
Class cplustestcase: Public cppunit: testcase {cppunit_test_suite (cplustestcase); cppunit_test (testadd); cppunit_test_suite_end (); Public: cplustestcase (); Virtual ~ Cplustestcase (); void testadd (); // test method }; |
|
Have you seen these macros? They showed up here. |
|
Cppunit_test_suite (cplustestcase ); |
Cppunit_test (testadd ); |
Cppunit_test_suite_end (); |
|
With these macros, we have registered cplustestcase and testadd to the test list. |
In addition, we need to add another macro to the CPP file: |
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CPlusTestCase,PlusTest::plusSuiteName() ); |
|
It registers the testsuite cplustestcase to a specified testfactory. This testsuite is identified by the name returned by the plustest: plussuitename () function () in the function, the name is used to obtain the factory ). Plussuitename () is a function in the namespace of plustest. It returns the name we created for this testsuite (in this example, we named "plus "). In fact, we do not need to do this, simply write "plus" in the macro. However, this prevents hard encoding from causing problems. |
|
In the test class, we added a Test method: |
|
void testAdd(); |
|
The test object is the method of the cplus class mentioned above: |
|
int Add(int nNum1, int nNum2); |
|
Let's take a look at its implementation: |
|
Void cplustestcase: testadd () {cplus plus; int nresult = plus. add (10, 20); // execute the add operation cppunit_assert_equal (30, nresult); // check whether the result is equal to 30} |
|
Cppunit_assert_equal is a macro that determines the result. For other macros similar to cppunit, see testassert. H. This article will not detail them here. |
In addition, we can override the setup () and teardown () Functions of the base class. These two functions are actually a template method. Before the test is run, setup () is called for initialization. After the test is completed, teardown () is called () to do some "aftercare", such as resource recycling. Of course, you can also not override these two functions, because they are defined as empty methods in the base class, rather than pure virtual functions. |
|
In addition, add the header file to CPP: |
#include "plusSuite.h" |
|
4. Compile the product code based on the test code |
Compile the test code above. The compiler will tell us that the cplus class is not declared, because we have not implemented the cplus class yet! The current job is to implement the cplus class immediately and let the compilation pass. Now you should smell a little bit of "test drive? |
|
Create a project of MFC extension DLL in VC and add the class cplus to this project. Its declaration is as follows: |
|
class AFX_EXT_CLASS CPlus { public: CPlus(); virtual ~CPlus(); public: int Add(int nNum1, int nNum2); }; |
|
There is only one method, that is, the method for testing the test code. Let's take a look at its implementation: |
|
int CPlus::Add(int nNum1, int nNum2) { return nNum1+nNum2; } |
|
It's very simple, isn't it? Now let the previous project dependent that contains the test code, the include header file, rebuild all, and you will find that the compilation has passed. Have you realized that the test code is driving the product code? Of course, our example is still very simple, and we have not reconstructed this step. |
Run our test program and you will see the 6 interface: |
Figure 6 |
Click Browse, 7: |
Figure 7 |
Now you should have a better understanding of the testsuite name we mentioned earlier. Plus is a test suite, which contains a test case, which contains a test method. |
|
So far, we have made a detailed introduction to the application of the cppunit testing framework, hoping to help you in the TDD process. |
|
References: |
Cppunit source code and instructions |
|
Cppunit testing framework (1) |
|
|