First of all, please forgive me for my bad English if it annoys you. Few months ago, I came to know about CPP Unit which is a unit testing framework for C++ application. I am a fresh guy out of college last year and was unaware about testing frameworks, so it was a very good experience for me to work with CPP Unit. As I was also programming on Windows CE, there was a need to write test cases for those applications also. But the problem with CPP Unit is that I was not able to compile for Windows CE as it used some features of C++ which are not supported by eVC++ compiler. I tried to search a similar test framework for Windows CE but I didn't find it. So after prolonged searching, I thought to write my own unit testing framework for Windows CE based applications. And this is what I came up with and I want to share with all.
This is a unit testing framework for applications written for Windows CE in particular. It provides GUI to select and run test cases, and to show results. It also stores the results of tests run to a file, if user wants.
Programming in C++ for WinCE is very restrictive. It does not support templates, RTTI and other stuff of C++. CPP Unit uses templates and RTTI, but in eVC++ it's not available. That's why I have used lots of member function pointers and call backs to implement it.
Using the Frame Work
Compile the WCEUnit project to make WCEUnit.dll file for a particular platform. In order to use the testing framework, the test case project must be linked with the WCEUnit.dll. Write your test cases and link the project to WCEUnit.dll. Following topics discuss how to write test cases.
Writing Test Cases
When you write a test class, it should be derived from
CTestSuite class defined in the framework. The
CTestSuite class holds all the information about the test cases written for that particular suite. The individual test cases should be added to the test suite as show in the following example. The macros which are used in the following example are defined in the WCEMacros.h header file. These macros wrap the test case addition mechanism. The below code shows a test suite class written for testing
CComplex class. The
CComplex class is very simple, and does primary implementation of complex numbers, and I will not go into the details of that one.
class CTestComplex : public CTestSuite
Pass test suite class name to it. This function defines the starting of a
CreateTestSuite() function. This function is defined as pure virtual in the
CTestSuite class and is used to create the test case lists.
This macro adds the code to the
CreateTestSuite() function to add a test case function.
This macro is used to add a special type of test case function which should be tested for a particular type of exception. If the test case does not throw the exception then it is considered to fail.
This macro ends the
You can see functions
CleanUpTest() in the definition of the class. These functions are called before and after every test case execution. From the UI, you can select the behavior about these functions, i.e., whether you want those functions to be called for every test case or only once for all the test cases for a particular test suite class. You can specify your choice by checking or un-checking the Init Once check box on the main dialog.
Writing Test Conditions
While writing test cases, use macros defined in the WCEUnitMacros.h for writing the test conditions. Following are the macros used to write test conditions:
condition is evaluated to false then it asserts and marks the test as failed.
This is reverse of above macro. If you want that the condition must return false then use this macro to test the condition.
This macro asserts if the
compValue are not equal. If the two values are not equal then it marks the test case as failed. If you are using some user defined class objects to compare then the class must have '
==' operator overloaded.
This macro is similar to the above one but it assumes that the
compValue are convertible to a
double value. It type casts the results into a
double value and then compares.
WCEUNIT_DOUBLE_BETWEEN(testValue, minValue, maxValue)
This macro tests weather the
testValue is less than
maxValue and greater than
minValue. It is assumed that the three values of expressions are evaluated to
double. The following code shows the usage of the above macros.
Following code shows the use of above macros in test cases for
temp = *m_p1 + *m_p2;
WCEUNIT_ASSERT(CComplex(30, 70) == temp);
WCEUNIT_ASSERT_FAIL(temp2 == *m_p3);
temp1 = *m_p1 + *m_p2;
m_p1 = new CComplex(10, 20);
m_p2 = new CComplex(20, 50);
m_p3 = new CComplex(30, 70);
Running Test Cases
CTestRunner class is responsible for running the test cases and getting the test results. To run the test cases you have written, create an instance of
CTestRunner class. Also create the instance of all the test suite classes, and pass the address of each in the
AddTestSuite() function of
CTestRunner class. Then call
Start() function of
CTestRunner. The following code shows how to run test cases:
The above image shows the main dialog. To select a test case to run, click the Select button, a new dialog will appear with the tree view of the test cases written by you. You can either select single test case or a test suite or All Tests. If you want to run all the test cases for a particular test suite then select that test suite, or if you want to run all the test cases of all the test suites then select the root node All Tests. The check box Init once is given for the option when the
CleanUpTest() will be called. If it is checked then for each test suite, the
CleanUpTest() is called only once respectively, before and after all the test cases are executed. If it is unchecked then for each and every test case, these two functions are called. Click the Run button to run the selected test cases. The results are displayed in the list box. If you want to see more information then just click the result item, you will be shown the detailed result. If you want to store the test results in a text file then check the Make log check box, a file \\WCEUnitLog.txt is created with the detailed test result information.
Points of Interest
During the development of this project, I learned a lot about the pointer to member functions in C++. They are amazing things and do a lot more than what you can imagine. May be next time, I will try to post some thing about pointer to member functions.