Using CppUnit with Visual Studio
It is a unit testing framework ( a port of JUnit ) for C++ .
The benifit of having a unit testing procedure is that , you can use it either in Test Driven Development or as a standalone test (for testing when needed).
With CPPunit, its very easy to write and run unit tests, as well as integrate the runs with the build process.
Installing CppUnit
The first thing is, there is no installation. The distribution is the source code which must be compiled with the compiler you are using for your C++ work.
Setting up CPPUnit (on windows using Visual Studio):
- Download latest release of CPPUnit
- Extract the zip contents.
- Open the Visual Studio 6 workspace file in the examples directory of the extracted folder.
- If you are using Visual Studio 2005 or 2008, it wont compile out of the box.
Fix For Visual studio 2005 and 2008
Open file MsDevCallerListCtrl.cpp in the folder srcmsvc6testrunner.
Find the following line
#import "libid:80cc9f66-e7d8-4ddd-85b6-d9e6cd0e93e2" version("7.0") lcid("0") raw_interfaces_only named_guids |
and change the version("7.0") to:
version("8.0") for VS 2005
version("9.0") for VS 2008
Now do a batch build for all configurations.
Dont worry about errors yet.
Go and look into the lib directory in the cppunit directory.
if you have cppunit.lib, cppunit_dll.lib and cppunit_dll.dll, then you are ready to go.
Adding the include and lib paths to Visual Studio environment
open Tools->Options.
Choose Projects and Solutions -> VC++ Directories
from the dropdown for "Show directories for" choose "Include Files"
and add(by clicking in the blank space on the bottom) -> <cppunit directory>include
for "Library files"
Add-> <cppunit directory>lib
Using it in a project
Read the Cookbook to get an idea how CPPUnit works.
Open the visual studio solution for the project you want to integrate testing into.
The Add a new project to the solution (this will be our testing project).
Open this new project's properties.
in the linker section under input. Add the cppuni.lib or cppunit_dll.lib (depending on you code generation options) to the Additional Dependencies.
For this to work either the .lib files should be in a directory in the include paths (it should be if you followed this entry from the top) or should be included in the project (by add item).
Add a header file ( for reference i'll name it test.h)
Include the header files for classes you want to test from the other project. Like this:
#include "../<project name>/<header file>" |
also include the following files
#include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TextTestRunner.h> |
you may exclude the test runner from here and include it in the cpp file with main function.
make a class that extends the the CppUnit::TestFixture class.
For example:
class g3Test : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( g3Test); CPPUNIT_TEST( testRun ); CPPUNIT_TEST_SUITE_END(); public: void testRun(){ CPPUNIT_ASSERT_EQUAL(1.2f, greater3(1.2, 0.26, -1.2) ); CPPUNIT_ASSERT_EQUAL(0.0f, greater3(-3.2, -1, 0) ); CPPUNIT_ASSERT_EQUAL(3.0f, greater3(2, 3, 2) ); CPPUNIT_ASSERT_EQUAL(5.1f, greater3(5.1, 5.1, 5.1) ); CPPUNIT_ASSERT_EQUAL(61.02f, greater3(61.02, 61.02, 1) ); CPPUNIT_ASSERT_EQUAL(-5.0f, greater3(-26, -10, -5) ); } }; |
the macro CPPUNIT_TEST_SUITE(
CPPUNIT_TEST(
And the Suite is ended using CPPUNIT_TEST_SUITE_END(); macro.
Apart from the testing functions.
Two more functions can be defined, which are automatically run.
1. void setUp();
2. void tearDown();
as the name suggests. Setup is run at start of test case execution and tearDown at end.
Thus setUp can be used for any sort of initialization and tearDown for any cleanup sfter test completion.
The cpp file where the tests are run
include the following files in the cpp file
#include "test.h" #include <cppunit/TextTestRunner.h> //(not needed if included in test.h) |
Define a main function
int main(int argc, char * argv[]) |
You can do any processing or output in this function.
To run the tets do the following:
CppUnit::TextTestRunner runnerText; runnerText.addTest( g3Test::suite() ); runnerText.run(); |
The above code does the following tasks:
1. create an instance of the testRunner class (you can also use MFC or QT test runner)
2. add tests using the automatic suite creation function of our test class
3. Run tests
The test runner will display the result.
To get the screen to hold you can add getch() at the end.
Thanks for reading.
This was about the basics of CPPUnit. I will post further entries for examples and build automation.
October 1st, 2017 - 19:23
I see you don’t monetize your site, don’t waste your traffic, you
can earn extra bucks every month because you’ve got high quality content.
If you want to know how to make extra bucks, search for: Mrdalekjd methods for $$$
March 16th, 2016 - 22:19
I read this article completely regarding the comparison of newest
and previous technologies, it’s awesome article.
May 13th, 2013 - 06:36
Well, now that we have our unit tests running, how about integrating unit testing to our build process ?
October 1st, 2011 - 12:46
thanks. it worked out well
but i’ve been using a simpler ver:
CPPUNIT_ASSERT_EQUAL(1,1); // PASS
August 10th, 2011 - 05:35
While i click on your Rss it looks as being a whole lot of weird text message, may be the issue on my own aspect?
March 21st, 2011 - 15:11
@Chris
Chris,
I am also getting a lot of linker errors. can you pls explain how did you solve this problem. I didnt understand which files did you delete….?
October 6th, 2010 - 05:27
This is a life saver!!! thanx for the effort
July 30th, 2010 - 19:32
Nevermind, I got it.
July 30th, 2010 - 15:54
Or how can I get the actual files and not the CVS files?
July 30th, 2010 - 15:51
Where can I get files without “,v” in the extension?
February 16th, 2010 - 21:38
I deleted my files and restarted, and got it to work.
February 16th, 2010 - 20:09
I added the cppunit*.lib files in my Additional files, and now am getting this…
1>Linking…
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: __thiscall std::basic_string<char,struct std::char_traits,class std::allocator >::basic_string<char,struct std::char_traits,class std::allocator >(char const *)” (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) already defined in HelloTester.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: char const * __thiscall std::basic_string<char,struct std::char_traits,class std::allocator >::c_str(void)const ” (?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ) already defined in HelloTester.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: class std::basic_string<char,struct std::char_traits,class std::allocator > & __thiscall std::basic_string<char,struct std::char_traits,class std::allocator >::operator=(char const *)” (??4?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV01@PBD@Z) already defined in libcpmtd.lib(locale0.obj)
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: __thiscall std::basic_string<char,struct std::char_traits,class std::allocator >::~basic_string<char,struct std::char_traits,class std::allocator >(void)” (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in HelloTester.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: __thiscall std::basic_string<char,struct std::char_traits,class std::allocator >::basic_string<char,struct std::char_traits,class std::allocator >(class std::basic_string<char,struct std::char_traits,class std::allocator > const &)” (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@ABV01@@Z) already defined in HelloTester.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: __thiscall std::_Container_base_secure::~_Container_base_secure(void)” (??1_Container_base_secure@std@@QAE@XZ) already defined in HelloTester.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)” (?_Debug_message@std@@YAXPB_W0I@Z) already defined in libcpmtd.lib(stdthrow.obj)
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: __thiscall std::_Lockit::~_Lockit(void)” (??1_Lockit@std@@QAE@XZ) already defined in libcpmtd.lib(xlock.obj)
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: __thiscall std::_Lockit::_Lockit(int)” (??0_Lockit@std@@QAE@H@Z) already defined in libcpmtd.lib(xlock.obj)
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: void __thiscall std::_Container_base_secure::_Orphan_all(void)const ” (?_Orphan_all@_Container_base_secure@std@@QBEXXZ) already defined in HelloTester.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: “public: __thiscall std::_Container_base_secure::_Container_base_secure(void)” (??0_Container_base_secure@std@@QAE@XZ) already defined in HelloTester.obj
1>MSVCRTD.lib(MSVCR90D.dll) : error LNK2005: “public: virtual __thiscall std::exception::~exception(void)” (??1exception@std@@UAE@XZ) already defined in LIBCMTD.lib(stdexcpt.obj)
1>MSVCRTD.lib(MSVCR90D.dll) : error LNK2005: “public: __thiscall std::exception::exception(void)” (??0exception@std@@QAE@XZ) already defined in LIBCMTD.lib(stdexcpt.obj)
1>MSVCRTD.lib(MSVCR90D.dll) : error LNK2005: “public: __thiscall std::exception::exception(class std::exception const &)” (??0exception@std@@QAE@ABV01@@Z) already defined in LIBCMTD.lib(stdexcpt.obj)
1>MSVCRTD.lib(MSVCR90D.dll) : error LNK2005: __invalid_parameter already defined in LIBCMTD.lib(invarg.obj)
1>MSVCRTD.lib(MSVCR90D.dll) : error LNK2005: __CrtDbgReportW already defined in LIBCMTD.lib(dbgrptw.obj)
1>MSVCRTD.lib(MSVCR90D.dll) : error LNK2005: “public: __thiscall std::exception::exception(char const * const &)” (??0exception@std@@QAE@ABQBD@Z) already defined in LIBCMTD.lib(stdexcpt.obj)
1>MSVCRTD.lib(MSVCR90D.dll) : error LNK2005: _memmove_s already defined in LIBCMTD.lib(memmove_s.obj)
1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: “private: __thiscall type_info::type_info(class type_info const &)” (??0type_info@@AAE@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: “private: class type_info & __thiscall type_info::operator=(class type_info const &)” (??4type_info@@AAEAAV0@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
1>LINK : warning LNK4098: defaultlib ‘MSVCRTD’ conflicts with use of other libs; use /NODEFAULTLIB:library
1>LINK : warning LNK4199: /DELAYLOAD:OleAcc.dll ignored; no imports found from OleAcc.dll
February 16th, 2010 - 19:51
I created a separate solution file for the project that has the test code, instead of adding the project in the solution file for the code I wanted to test. Other than that, I followed all the above instructions, including adding the cppunit…include and …lib dirs in VS2008 -> Tools menu.
I get the following link errors.
1>HelloTester.obj : error LNK2019: unresolved external symbol “public: __thiscall CppUnit::SourceLine::SourceLine(class std::basic_string<char,struct std::char_traits,class std::allocator > const &,int)” (??0SourceLine@CppUnit@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z) referenced in function “public: void __thiscall HelloTester::testRun(void)” (?testRun@HelloTester@@QAEXXZ)
1>HelloTester.obj : error LNK2019: unresolved external symbol “public: virtual __thiscall CppUnit::SourceLine::~SourceLine(void)” (??1SourceLine@CppUnit@@UAE@XZ) referenced in function “void __cdecl CppUnit::assertEquals(int const &,int const &,class CppUnit::SourceLine,class std::basic_string<char,struct std::char_traits,class std::allocator > const &)” (??$assertEquals@H@CppUnit@@YAXABH0VSourceLine@0@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>HelloTester.obj : error LNK2019: unresolved external symbol “public: static void __cdecl CppUnit::Asserter::failNotEqual(class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::basic_string<char,struct std::char_traits,class std::allocator >,class CppUnit::SourceLine const &,class CppUnit::AdditionalMessage const &,class std::basic_string<char,struct std::char_traits,class std::allocator >)” (?failNotEqual@Asserter@CppUnit@@SAXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@0ABVSourceLine@2@ABVAdditionalMessage@2@0@Z) referenced in function “void __cdecl CppUnit::assertEquals(int const &,int const &,class CppUnit::SourceLine,class std::basic_string<char,struct std::char_traits,class std::allocator > const &)” (??$assertEquals@H@CppUnit@@YAXABH0VSourceLine@0@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>HelloTester.obj : error LNK2019: unresolved external symbol “public: __thiscall CppUnit::AdditionalMessage::AdditionalMessage(class std::basic_string<char,struct std::char_traits,class std::allocator > const &)” (??0AdditionalMessage@CppUnit@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function “void __cdecl CppUnit::assertEquals(int const &,int const &,class CppUnit::SourceLine,class std::basic_string<char,struct std::char_traits,class std::allocator > const &)” (??$assertEquals@H@CppUnit@@YAXABH0VSourceLine@0@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
February 14th, 2010 - 08:52
Ignore my comment. I got the *.tar.gz file and unzipped it with 7zip.
February 14th, 2010 - 06:56
The download site you link to has a *.bz2 file, not *.zip. Will the *.bz2 file have the *.zip file?
December 12th, 2009 - 09:21
Wow, I didn’t know about this topic until now. Thanks!!
November 20th, 2009 - 00:52
Lifesaver. Thanks Man.
Appreciated!
🙂