Click here to Skip to main content
Click here to Skip to main content

Unit Testing Framework for eVC++ Applications

, 17 Oct 2004
Rate this:
Please Sign up or sign in to vote.
A unit testing framework for eVC++ applications, and its usage.

Introduction

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.

Background

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.

//TestComplex.h

#ifndef __TEST_COMPLEX_INCLUDED__
#define __TEST_COMPLEX_INCLUDED__

#include "..\WCEUnit\TestSuite.h"
#include "..\WCEUnit\WCEUnitMacros.h"
#include "Complex.h"

class CTestComplex : public CTestSuite
{
public:
    //Pass the name of the test class as parameter.
    WCEUNIT_TESTSUITE_INIT(CTestComplex);
    //Pass the name of the test case function as parameter.
    WCEUNIT_ADD_TESTCASE(testAdd);
    WCEUNIT_ADD_TESTCASE(testEqual);
    WCEUNIT_ADD_TESTCASE_EXCEPTION(testExcp, CUserException);
    WCEUNIT_TESTSUITE_END();

public:
    /***********************************************************
    The signature of test case function should be void (func)();
    ***********************************************************/
    void testAdd();
    void testEqual();
    void testException();
    void CleanUpTest();
    void InitializeTest(); 
private:
    CComplex*        m_p1;
    Ccomples*        m_p2;
    CComplex*        m_p3;
};
#endif //__TEST_COMPLEX_INCLUDED__

Macro description

  • WCEUNIT_TESTSUITE_INIT(testSuite)

    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.

  • WCEUNIT_ADD_TESTCASE(testCase)

    This macro adds the code to the CreateTestSuite() function to add a test case function.

  • WCEUNIT_ADD_TESTCASE_EXCEPTION(testCase, testException)

    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.

  • WCEUNIT_TESTSUITE_END()

    This macro ends the CreteTestSuite() function.

You can see functions InitializeTest() and 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:

  • WCEUNIT_ASSERT(condition)

    If the condition is evaluated to false then it asserts and marks the test as failed.

  • WCEUNIT_ASSERT_FAIL(condition)

    This is reverse of above macro. If you want that the condition must return false then use this macro to test the condition.

  • WCEUNIT_ASSERT_EQUALS(testValue, compValue)

    This macro asserts if the testValue and 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.

  • WCEUNIT_DOUBLE_EQUALS(testValue, compValue)

    This macro is similar to the above one but it assumes that the testValue and 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 CComplex class.

void CTestComplex::testAdd()
{
    CComplex temp;
    temp = *m_p1 + *m_p2;
    WCEUNIT_ASSERT(CComplex(30, 70) == temp);
}

void CTestComplex::testEqual()
{
    CComplex temp2;            //Below test should fail.
    WCEUNIT_ASSERT_FAIL(temp2 == *m_p3);

    CComplex temp1;            //Below test should pass.
    temp1 = *m_p1 + *m_p2;
    WCEUNIT_ASSERT_EQUALS(temp1, *m_p3);

    //To check the equality of the real and imaginary members.
    WCEUNIT_DOUBLE_EQUALS(temp1.GetReal(), m_p3->GetReal());
    WCEUNIT_DOUBLE_EQUALS(temp1.GetImaginary(), m_p3->GetImaginary());
}

void CTestComplex::testException()
{
    //This fuction is only to demonstrate the exception test.
    //It throws CUserException. This test will fail as the expected exception
    //is CFileException.

    CUserException e;
    THROW(&e);
}

void CTestComplex::InitializeTest()
{
    m_p1 = new CComplex(10, 20);
    m_p2 = new CComplex(20, 50);
    m_p3 = new CComplex(30, 70);
}

void CTestComplex::CleanUpTest()
{
    delete m_p1;
    delete m_p2;
    delete m_p3;
}

Running Test Cases

The 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:

BOOL CTestComplexApp::InitInstance()
{
    //Create the instance of CTestRunner class.
    CTestRunner obj;
    //Create the instance of CTestComplex test suite class.
    CTestComplex test1;

    //Pass the address of CTestComplex instance to the AddTestSuite() function.
    obj.AddTestSuite(&test1);

    //Sart the WCEUnit dialog to run the test cases.
    obj.Start();
    return FALSE;
}

The GUI

WCEUnit/wceunit.jpg

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 InitializeTest() and CleanUpTest() will be called. If it is checked then for each test suite, the IntializeTest() and 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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Abdul Munaf Chhatra
Web Developer
India India
A person who like to know about new things, peolple and make frineds. I strarted programming in 2000 with fortran but my first love in programming is C++. Also programmed in VB, MFC and for Windows CE.
 
Graduated in Physics and done masteres in Computer application. Physics and astronomy are my area of intrest. Karate is also one of my hobbies, BTW I am a Black Belt in Karate.

Comments and Discussions

 
GeneralGPIO Pinmemberasdfgh12345asdfgh24-Mar-10 10:30 
QuestionHow to link the DLL? Pinmemberdurgakul18-Jun-09 8:54 
AnswerRe: How to link the DLL? PinmemberAbdul Munaf Chhatra23-Jun-09 21:35 
GeneralRe: How to link the DLL? Pinmemberdurgakul30-Jun-09 4:03 
GeneralRe: How to link the DLL? PinmemberAbdul Munaf Chhatra2-Jul-09 5:14 
GeneralRe: How to link the DLL? Pinmemberdurgakul2-Jul-09 8:19 
GeneralRe: How to link the DLL? PinmemberAbdul Munaf Chhatra2-Jul-09 21:40 
GeneralRe: How to link the DLL? Pinmemberdurgakul9-Jul-09 12:38 
QuestionDoes this framework support VS2005 ? Pinmemberbigo103014-Jul-08 20:53 
AnswerRe: Does this framework support VS2005 ? PinmemberAbdul Munaf Chhatra15-Jul-08 18:42 
GeneralRe: Does this framework support VS2005 ? Pinmemberbigo103015-Jul-08 21:43 
GeneralRe: Does this framework support VS2005 ? PinmemberAbdul Munaf Chhatra16-Jul-08 2:35 
GeneralRe: Does this framework support VS2005 ? Pinmemberbigo103016-Jul-08 7:47 
Generala simple program in EMP Pinmembersireeshakolluri7-Apr-08 22:09 
GeneralThe code does not work ... Pinmembernathan_jing24-Oct-06 13:43 
QuestionHow to get the WCEUnit.dll ? Pinmemberhoward200625-Aug-06 4:48 
AnswerRe: How to get the WCEUnit.dll ? PinmemberAbdul Munaf Chhatra14-Nov-06 22:27 
GeneralMember function pointers PinmemberDon Clugston27-Oct-04 13:33 
GeneralRe: Member function pointers PinmemberAbdul Munaf Chhatra2-Nov-04 23:21 
GeneraleVC 3 and templates PinsussAndy Oliver26-Oct-04 22:32 
GeneraleVC4 is supposed to support STL and RTTI PinmemberJim Crafton18-Oct-04 8:26 
GeneralRe: eVC4 is supposed to support STL and RTTI Pinmemberjan.vorlicek20-Oct-04 3:55 
GeneralRe: eVC4 is supposed to support STL and RTTI PinmemberJim Crafton20-Oct-04 14:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 18 Oct 2004
Article Copyright 2004 by Abdul Munaf Chhatra
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid