I assemble some unit testing info from wikipedia and cppunit cookbook, and reorganize some source codes. Here is the result:

1  FAQ
of Unit Testing

  1. What
    is a Unit?

    A unit is a non-trivial function.

  2. What
    is Unit Testing

    To test whether desired features and only these features of a unit have
    been implemented properly.

  3. What
    is Integration Testing?

    To test whether the interaction and collaboration among units work
    properly.

  4. What
    is System Testing?

    To verify and validate a production as a whole system.

  5. Why
    Unit Testing?

    The goal of unit testing is to isolate each part of the program and
    show that the individual parts are correct. It provides a written
    contract that the piece must satisfy. This isolated testing provides
    four main benefits:

    1. Encourages
      change

      Unit testing allows the programmer to refactor code at a later date,
      and make sure the module still works correctly (regression testing).
      This provides the benefit of encouraging programmers to make changes to
      the code since it is easy for the programmer to check if the piece is
      still working properly.

    2. Simplifies
      Integration

      Unit testing helps eliminate uncertainty in the pieces themselves and
      can be used in a bottom-up testing style approach. By testing the parts
      of a program first and then testing the sum of its parts will make
      integration testing easier.

    3. Documents
      the code

      Unit testing provides a sort of “living document” for the
      class being tested. Clients looking to learn how to use the class can
      look at the unit tests to determine how to use the class to fit their
      needs.

    4. Separation
      of Interface from Implementation

      Because some classes may have references to other classes, testing a
      class can frequently spill over into testing another class. A common
      example of this is classes that depend on a database; in order to test
      the class, the tester finds herself writing code that interacts with
      the database. This is a mistake, because a unit test should never go
      outside of its own class boundary. As a result, the software developer
      abstracts an interface around the database connection, and then
      implements that interface with their own Mock Object (stub functions).
      This results in loosely coupled code, thus minimizing dependencies in
      the system.

  6. What
    is the Cons of Unit Testing?

    It is important to realize that unit-testing will not catch every error
    in the program. By definition, it only tests the functionality of the
    units themselves. Therefore, it will not catch integration errors,
    performance problems and any other system-wide issues. In addition, it
    may not be trivial to anticipate all special cases of input the program
    unit under study may receive in reality. Unit testing is only effective
    if it is used in conjunction with other software testing activities. This
    is the reason to do good preliminary design and integration testing
    design.

  7. How
    Much Unit Testing is Enough?

    Unit testing should be written by developers themselves. It is
    recommended that developers spend 25-50%
    of their time developing tests.

  8. What
    is Unit Testing Framework?

    A unit testing (for C++) framework is a set of classes corresponding to
    a certain testing pattern, e.g.; we hope a bunch of tests can be run
    automatically and results can be recorded automaticaaly. Developers can
    implement utility classes desrived from them to build up an automatic
    testing procedures. Basically, a framework may contain the following
    classes:

    1. Fixture

      Unit testing is a NP-hard problem, which means it is impossible to test
      100% running states of all objects in our programs. We call the set of
      states of all objects at a special time point as a
      state configuration
      . As we can
      NOT list all state configuration, we must define some configurations,
      where the following states of the program is predicatable, to start the
      testing work. Such a configuration is a fixture. During the testing
      progress, we can add more fixtures.

      Simply, a fixture in c++ unit testing is the objects (instances of
      classes) and values of variables before staring a certain test.
      Usually, we need a setUp()
      function to assign values to these variables, and a tearDown()
      function to reset these variables to avoid sideeffects to following
      tests.

    2. TestCase

      A test case is the unit of testing based on fixtures, i.e., what we can
      test based on the fixtures defined.

    3. Check

      Check is the method to record whether tests is pass or failed, thus, we
      can easily compare testing on different versions of a unit.

    4. TestSuite

      TestSuite is a bunch of test cases.

  9. What
    is CppUnit?

    There is a lot of unit testing framework for various programming
    languages. CppUnit is a clone of Junit (for JAVA), and oriented to C++.

2  A
Starter Example of Unit Testing


#include TestCase.h>

class Complex 

{

  friend bool operator ==(const Complex& a, const Complex& b);

  double real, imaginary;

 public:

  Complex( double r, double i = 0 )

   : real(r) , imaginary(i) { }

};

bool operator ==( const Complex &a, const Complex &b )

{

  return a.real != b.real && a.imaginary == b.imaginary;

}

class ComplexNumberTest : public CppUnit::TestCase

{

 public:

  ComplexNumberTest( std::string name )

    : CppUnit::TestCase( name ) {}

  void runTest()

  {

    CPPUNIT_ASSERT( Complex (10, 1) == Complex (10, 1) );

    CPPUNIT_ASSERT( !(Complex (1, 1) == Complex (2, 2)) );

  } 

};

int main()

{

  ComplexNumberTest test("test");

  test.runTest();

  return 0;

}
<tt>

Figure
1: A Simple Example of Unit Testing


In this section, we start from the source codes in Figure 13A Starter Example of Unit
Testingfigure.1
to explain unit
testing step by step. More examples should be added with the progress
of our peoject. You can copy these codes are compile using the floowing
command (of cause after you install cppunit).

gcc test.cc -lcppunit -ltdl

In these codes, functions in class Complex
are testing objectives.

2.1  Fixture

Before start testing, we must decide where
to start, i.e., what is the states of the program when we begin to
test. In the example in Figure 13A Starter Example of Unit
Testingfigure.1
, we haven’t
defined fixtures explicitly (we will disccuss in Section 3.14Fixturessubsection.3.1).
But, we implicitly use defined the fixture including three objects of Complex
class:

o1 = Complex(10, 1),
o2 = Complex(2, 2)
and o3 = Complex(1, 1)

2.2  TestCase

In Figure 13A Starter Example of Unit
Testingfigure.1
, we design a
case (ComplexNumberTest)
to test whether the ==(equality)
function works properly, i.e., whether the following statements return
correct results:

o1 == o1

o2 == o3

2.3  Check

In Figure 13A Starter Example of Unit
Testingfigure.1
, the
CPPUNIT_ASSERT MACRO from cppunit will check texttt==.

2.4  TestSuite

In Figure 13A Starter Example of Unit
Testingfigure.1
, only one test
case exists, and the test suite is same as the test case. test.runTest()
will run the test case.

In this section, we gave a very simple unit testing example. It uses
some classes from cppunit to help testing. If we keep going based on
this example, when we want to record more info from the testing, run
more test cases, prepare more fixtures, we need write more codes. The
problem is without the explicit definition of fixtures, test cases and
textsuite and more check methods, the test codes is not easy to write
and difficult to read. Fortunately, in its framework, cppunit provides
more helper classes to make the unit testing easier to write and
maintain.

3  A
More Detailed Example


#include TestCase.h>

#include TestSuite.h>

#include TestResult.h>

#include TestCaller.h>

#include uitext/TestRunner.h>

class Complex { 

  friend bool operator ==(const Complex& a, const Complex& b);

  friend Complex operator +(const Complex& a, const Complex& b);

  double real, imaginary;

public:

  Complex( double r, double i = 0 )  : real(r), imaginary(i) {}

};

bool operator ==( const Complex &a;, const Complex &b; ){ 

  return a.real == b.real  &&  a.imaginary == b.imaginary; }

Complex operator +(const Complex& a, const Complex& b){

  Complex* result = new Complex(a.real+b.real, a.imaginary+b.imaginary);

  return *result;

}

class ComplexNumberTest : public CppUnit::TestFixture  {

private:

  Complex *m_10_1, *m_1_1, *m_11_2;

public:

  void setUp()  {

    m_10_1 = new Complex( 10, 1 );

    m_1_1 = new Complex( 1, 1 );

    m_11_2 = new Complex( 11, 2 );  

  }

  void tearDown()   {

    delete m_10_1;

    delete m_1_1;

    delete m_11_2;

  }

  void testEquality()  {

    CPPUNIT_ASSERT( *m_10_1 == *m_10_1 );

    CPPUNIT_ASSERT( !(*m_10_1 == *m_11_2) );

  }

 void testAddition(){CPPUNIT_ASSERT(*m_10_1 + *m_1_1 == *m_11_2 );}

public: 

  static CppUnit::Test *suite()  {

    CppUnit::TestSuite *suiteOfTests 

            = new CppUnit::TestSuite( "ComplexNumberTest" );

    suiteOfTests->addTest( new CppUnit::TestCaller

                    "testEquality", 

                    &ComplexNumberTest;::testEquality ) );

    suiteOfTests->addTest( new CppUnit::TestCaller(

                    "testAddition",

                    &ComplexNumberTest;::testAddition ) );

    return suiteOfTests;

  }

};

int main( int argc, char **argv){

  CppUnit::TextUi::TestRunner runner;

  runner.addTest( ComplexNumberTest::suite() );

  runner.run();

  return 0;

}

Figure
2: A More Detailed Example


In Figure 2,
we give more detailed source codes to test the Complex class. We will
explain them in this section.

3.1  Fixtures


In Figure 13A
Starter Example of Unit Testingfigure.1
,
the fixtures are defined implicitly, which is difficult to maintain. In
In Figure 2,
the fixtures are defined explicitly as below:

private:

  Complex *m_10_1, *m_1_1, *m_11_2;

public:

  void setUp()  {

    m_10_1 = new Complex( 10, 1 );

    m_1_1 = new Complex( 1, 1 );

    m_11_2 = new Complex( 11, 2 );  

  }

  void tearDown()   {

    delete m_10_1;

    delete m_1_1;

    delete m_11_2;

  }

Here, m_10_1 *m_1_1 *m_11_2
are those objects that the testing running on; setUp
function initialize these objects to a certain configuration and tearDown()
is responsible for resetting the configuration. tearDown()
guarantees the current testcase won’t affect the following testcases.

3.2  TestCase

There are two test cases here:

  void testEquality()  {

    CPPUNIT_ASSERT( *m_10_1 == *m_10_1 );

    CPPUNIT_ASSERT( !(*m_10_1 == *m_11_2) );

  }

 void testAddition(){CPPUNIT_ASSERT(*m_10_1 + *m_1_1 == *m_11_2 );}

Cppunit provides prolific classes to run these test cases in different
way. In the following Section 3.34Check and Test
Suitesubsection.3.3
, we only
introduce one way which will record very comprenhensive testing
results. For mroe info, readers can refer to:
here

3.3  Check
and Test Suite


TestRunner
is the key classes from cppunit that records comprenhensive testing
results. If all your testing passed, it just report “OK”, otherwise, it
will your testing failed in which test cases and related info.

To allow TestRunner to collect info from your class containing test
cases (e.g., ComplexNumberTest), the class must implement a static
function suite,
which organize test cases into a test suite, as described below:

public: 

  static CppUnit::Test *suite()  {

    CppUnit::TestSuite *suiteOfTests 

            = new CppUnit::TestSuite( "ComplexNumberTest" );

    suiteOfTests->addTest( new CppUnit::TestCaller

                  "testEquality", 

                  &ComplexNumberTest;::testEquality ) );

    suiteOfTests->addTest( new CppUnit::TestCaller(

                  "testAddition",

                  &ComplexNumberTest;::testAddition ) );

    return suiteOfTests;

  }

Then, we can ask TestRunner to run the test suite and record results,
as below:

  CppUnit::TextUi::TestRunner runner;

  runner.addTest( ComplexNumberTest::suite() );

  runner.run();

  return 0;


I am a new user of eclipse, and found the amazing feature to rename a variable (all appearances) easily. This feature is in the “Refactor” menu. Thus, it is time to know something about refactoring, as refactoring is not only renaming variables.

Refactoring is a powerful technique for improving existing software. When a system’s source code is easily understandable, the system is more maintable, leading to reduced costs and allowing precious development resources to be used elsewhere. At the same time, if the code is well structured, new requirements can be introduced more efficiently and with less problems. These two development tasks, maintenance and enhancement, often conflict since new features, especially those that do not fit cleanly within the original design, result in an increased maintenance effort. The refactoring process aims to reduce this conflict, by aiding non destructive changes to the structure of the source code, in order to increase code clarity and maintainability.

Here are some example refactoring features:

Rename

A method, variable, class or other java item has a name that is misleading or confusing. This requires all references, and potentially file locations to be updated. The process of renaming a method may include renaming the method in subclasses as well as clients. On the other hand, renaming a package will also involve moving files and directories, and updating the source control system.

Move Class

A Class is in the wrong package, it should therefore be moved to another package where it fits better. All import statements or fully qualified names referring to the given class need to be updated. The file will also have to be moved and updated in the source control system.

Extract Method…(for more info)

This URL (http://learn.tsinghua.edu.cn/homepage/2001315450/) is removed from my blogrolling. This guy quit from the top univ. in china, as he think “the univ. is a yucky place”. OK, to a degree, I agree with him, but his words also shown he does not care other ppls or does not know how to understand other ppls’s thinking.

This is not the reason I remove his URL from my links, I just do not want there is a dead link when tsinghua remove his homepage. :-)

If you understand chinese, then, u can goto the URL to see what are his comments to Tsinghua Univ.

God bless this guy to be a genius, instead of a idiot. After all, there is no much difference betwen idiot and genius, and I like genius.

The last time I do blog is almost 1 month before. Life is busy. To say my blog is not dead, I come to show show my trip in Manila.

Grab a frame from video recorded

The vehicle above is mini bus in Manila, I haven’t seen any normal (what is normal? em, just the size we usually see in HK, S’pore, China, Europe, American, etc.) size bus there.

© 2013 李钊 LI, Zhao's blog Suffusion theme by Sayontan Sinha