What is cpp unit

The art of testing C++ code: An introduction to cppUnit

Before a motor company releases a new car, it must first be tested to make sure the steering, acceleration and brakes function correctly. Before releasing a new medical drug into the market, it undergoes strict testing to ensure it does what it claims with no undesired harm. In the same way, before any software is released into the wild, it should first be subjected to rigorous tests to try to confirm that each section of the code is bug free.

Unit testing, popularized as part of the framework for Xtreme Programming, is one possible method for code-testing based on testing every aspect of the code for well-defined behavior. To assist developers, unit testing code has been developed for many different platforms, commonly referred to as xUnit. TCS developers may recognize many listed there, such as jUnit, jsUnit, nUnit, and httpUnit (covered in this feature). cppUnit is the port of this framework for use with C++ projects.

Building your unit:

Before developing cppUnit code, it must be first built locally. Detailed information is available from the cppUnit wiki build page, and is summarized below. This process applies to those on a Unix machine or running cygwin under Windows:

  1. Obtain the source, available from cppUnit’s sourceforge download page. At the time of writing, the most recent stable version is 1.10.2
  2. Unpack locally by unzipping and untarring the download.
  3. Check configuration details available by reading the INSTALL-x file provided. Beware that some information provided about cygwin here is outdated and incorrect.
  4. Generate makefiles by running ./configure.
  5. Compile it all by calling make. This will output a lot of information to the console, and may include warnings, but hopefully no errors.
  6. Test the installation with make check. Yes, you are testing testing code!
  7. Install libraries and headers with make install.
    For those using Linux or cygwin, it may be useful to check first to see if cppUnit has already been installed. A good indication is to see if ./cppunit-config, a cppUnit utility, can run.
Читайте также:  Python индекс символа строке

If you are interested in using cppUnit from Windows using Visual Studio, there will be a .dsw file provided that allows you to test a project in the Post-Build phase. For more information, see the build page linked above. Also available are instructions to build cppUnit within Eclipse.

Unit interaction:

Unit testing with cppUnit is based around TestFixture instances, each of which contains a suite of test cases.

To write some tests of your own, first create a test class that extends publicly from the CppUnit::TestFixture class. Inside that you can then create as many void test methods as you like, performing various assertion tests using the multitude of helpful test macros provided by TestAsserts.h. For example, here is a method which tests the return value of a method multiple times, using most of the available macros:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class suiteOfTests: public CppUnit::TestFixture < /* snip */ public: void ageTest() < int age = ClassImTesting.getAge(); // simple asserts CPPUNIT_ASSERT(age == 18); CPPUNIT_ASSERT_MESSAGE("Must be 18", age == 18); // asserting equality: CPPUNIT_ASSERT_EQUAL(age, 18); CPPUNIT_ASSERT_EQUAL_MESSAGE("Must be 18", age, 18); CPPUNIT_ASSERT_DOUBLES_EQUAL(age * 1.0, 18.0, 1e-10); // exception asserts: CPPUNIT_ASSERT_THROW(ClassImTesting - > testAge(age - 1), WrongAgeException); CPPUNIT_ASSERT_NO_THROW(ClassImTesting - > testAge(age), WrongAgeException); // inverse asserts: if (age != 18) CPPUNIT_FAIL("Must be 18"); CPPUNIT_ASSERT_ASSERTION_FAIL(CPP_UNIT_ASSERT(age != 18)); > void setUp()  < . >// used to set up the require preconditions void tearDown()  < . >// called after tests are run, in order to clean up. >; 

As you can see, the macros provided give a variety of ways to test the code, including checking for boolean true/false, equality with optional epsilon, checking error handling, and manually failing or inverting an assertion. Each macro expands into a cppUnit assertion which includes a message (which you may provide in xx_MESSAGE macros) to help you find the test if it fails, as well as the line in the source from which it originates.

Читайте также:  Анимация выпадающего меню css

There are also two functions, setUp and tearDown, where you should put any logic that must be executed before or after the tests are run, respectively.

In addition it is simple to create your own assertions, including custom macros. Their creation is beyond the scope of this introduction, but a clear example is available here.

Declaration of intent:

The benefit to using a TestFixture comes when telling the rest of your code where your tests lie. Again, through the use of macros, cppUnit will automatically put all of your tests together in a testing suite, available statically. Use is self-explanatory, for example:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include  #include  class suiteOfTests: public CppUnit::TestFixture < // generation macros, using the class and method names CPPUNIT_TEST_SUITE(suiteOfTests); // use CPPUNIT_TEST_SUB_SUITE for subclasses, // to call inherited tests CPPUNIT_TEST(ageTest); // add each method name in a CPPUNIT_TEST call CPPUNIT_TEST(heightTest); // " " CPPUNIT_TEST_SUITE_END(); // generates the TestSuite* suite() method public: void ageTest()  < . >void heightTest()  < . >/* snip */ >; 

The result of these will be an additional two methods:
static void addTestsToSuite(…), which will be called by a tester to register all the methods found inside a CPPUNIT_TEST macro.
static CPPUNIT_NS::TestSuite *suite(), which returns a suite of tests that can be executed at runtime.

Final preparation:

  • Testing manually: Having written all these test cases, no doubt you’ll be wanting to execute them at some stage. cppUnit provides a TestRunner class that you can add TestSuites to, as well as execute by calling its run(…) method.
  • Testing using registry: It may not suprise you to learn that there is a more automated way of running tests, through use of macros found inside HelperMacros.h. As shown below, you can register your fixtures by putting their class name inside a CPPUNIT_TEST_SUITE_REGISTRATION macro. This will add the entire suite to a Factory registry, which can be obtained statically later and added to a TestRunner (see below).
  • XML generation: The default output for cppUnit is to print to the console the suite results, as well as any errors encountered. As with other xUnit ports, cppUnit provides a simple way to also output all results to an XML file. It is constructed as in instance of XmlOutputter as shown below, and added to the TestRunner before the suites are run.
    Other forms of output are supported, such as GUI using MFC or Qt depending on compile environment. It is also possible to create your own custom output formatters, feel free to explore the cppUnit wiki’s information about this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include #include  #include  #include  #include  // . CPPUNIT_TEST_SUITE_REGISTRATION(suiteOfTests); // . CppUnit::TestRunner runner; // creates a test executor // Specify XML output and inform the test runner of this format (optional) CppUnit::XmlOutputter * outputter = new CppUnit::XmlOutputter( & runner.result(), std::ofstream("result.xml")); runner.setOutputter(outputter); // use the suite factory, then execute all tests runner.addTest(CppUnit::TestFactoryRegistry::getRegistry() .makeTest()); runner.run("", false); 

All units go:

Once you have written your cppUnit code, the following should compile it using gcc, as long as the initial build step was successful. This assumes the main() method is in cppTester.cpp, and you want the executable to be called textExec (though the names are easily changed):
g++ $( cflags ) -o testExec cppTester.cpp .. [ any other . cpp / . o ] .. $( lflags ) where $( cflags ) are the required compiler flags, as found by running ./cppunit-config —cflags and $( lflags ) are the required librarys to be linked, found with ./cppunit-config —link

Debriefing:

Hopefully this introduction has introduced enough of cppUnit for you to start writing and running your own suite of tests.
However, cppUnit has many more features and options for you to explore if you wish. Some places to start include:

  • Documentation: http://cppunit.sourceforge.net/doc/lastest/index.html
  • cppUnit wiki: http://cppunit.sourceforge.net/cgi-bin/moin.cgi
  • Code Project article: http://www.codeproject.com/library/Using_CPPUnit.asp
    In addition, if you have any questions regarding cppUnit or this article in particular, feel free to ask at the forums.

Источник

What is cpp unit

First of all, I would like to acknowledge that this is a great article. I hope someone is still tracking this seven year old article.

I have a MFC project that generates a DLL. This does not generate an GUI instance. It just uses some AFX classes to perform some events on Windows shell instances. So unlike a typical MFC app, it does not have the CWinApp::initInstance method defined. In fact the primary class in this app does not even extend from CWinApp. I have a different app where some of the DLL’s methods are imported and used.

Now my question is, where do I initiate my unit tests from? In other words, where do I put the following piece of code —

Please respond. I’m stuck and am not able to find many resources.

As shown in the article you should create a dialog based app where you have to do the initializations. That project is part of your solution.

Your unit-test-class(es) (that are the classes derived from CppUnit::TestCase) have two options testing your MFC-DLL:
a) Referencing the DLL (e.g. thourgh a import library) and calling/testing all exported methods
b) directly reference the sources of your MFC-DLL

I just compile CppUnitLibraries, but when I excute «my_test» appplication a got an error :
an assert in MfcTestRunner::run(), dlg.DoModal();
the last fucntion call in CallStack is «AfxGetResourceHandle»

you should set charset configuration of both your testproject and testrunner project as multiset, or both set unicode because of default charset is unicode in vs2005.

BOOL addition(int a, int b) < return (a + b); >

Where BOOL should really be ‘int’ in the first place. One more reason to change all your ‘BOOL’s to ‘bool’s.

My conclusion? Before you go for complex testing, read you code. Then read it again.

Yes, BOOL is wrong, so it must be:

 
int addition(int a, int b)

And your conclusion is right: code review is really effective and must be mandatory.

You’re correct thats one more reason to use bool instead of BOOL because BOOL is defined as unsigned int .

Test test-cases in this article aren’t the best. You should also test with maximum values (max-int) and not just with 10, . What happens to the code if adding 4294967296 + 4294967296?

Seems to be a copy&paste error by the author of the article.

«Debug Assertion Failed!»
«Program: . »
«File: appcore.cpp»
«Line: 235»

and in the debug log, it gives me errors like,

«*** NOTE[cdxCDynamicWndEx::RestoreWindowPosition()]: To properly store and restore a window’s position, please call CWinApp::SetRegistryKey() in you app’s InitInstance() !»
«The thread ‘Win32 Thread’ (0xb08) has exited with code 3 (0x3).»

I am using Cppunit1.10.2. Does anyone have any suggestions?

However, I’m always so disapointed when I read articles about C++ that does not show some knowledge
of modern C++. That includes at the very least use of

— the standard library
— smart pointers/deterministic destruction

and hopefully some knowledge of exception-safety.
Code like this

// convert from relative to absolute path
TCHAR absoluteFilename[MAX_PATH];
DWORD size = MAX_PATH;

really worries me when you could use std::string.
And why isn’t this resource

encapsulated by a smart pointer?

You’re in truth, but this article focuses in CPPUnit, and I should write clear, common, easy, portable code, even that code isn’t as good as it could.

STL is great, but it isn’t full extended, perhaps due it’s too cryptic and extrange for normal users (most of us come from ANSI-C world).

Thanks for your opinion. It’s really usefull.

Pointing someone else error is really easy , don’t you think?
Coding style doesn’t show programmer knowledge , this article does not focus on
things like stl or secure programming .
What’s wrong with strcpy? , it is not safe for this article? who is going to xploit this code?
. this is just a fast introductory reading for mock.obj/CppUnit testing..
Be real Thorsten , stl is not good for everything , stl is not «modern» style C++.
Maybe you can share your great knowledge with us..(and SUYFM).

Источник

Оцените статью