You are here: Home » c programming » Simple Object Oriented Unit Testing For C Programming

Simple Object Oriented Unit Testing For C Programming

by David M. Doolin, PhD on January 3, 2011 · 3 comments

Recovery from giant blast of wind

Recovery from giant blast of wind

Remember that giant blast of wind a few months ago? The wind that launched all my cool plants down the stairs? Well, here’s a picture of the re-potted collection. That’s about half of them, the other half are still languishing. Crassulae are tough as nails. I may re-pot the remaining… but these need to be split out now. They’re a little overcrowded. (Update: I did split that pot and repot the remaining. Many of them ended up at my friend Ben’s house in Berkeley.)

From left to right: kalanchoe longifolia, unknown crassula, kalanchoe tubiflora, unknown sedum, kalanchoe serrata, unknown kalanchoe, another k. longiflora, sedum burrito, kalanchoe glaucesens, kalanchoe gastonis-bonnerai (hardly visible, very sick little plant), kalanchoe tomentosa, kalanchoe pumila. There’s a kalanchoe marmorata buried in there as well, but that one volunteered. Whew!

The important stuff dealt with, let’s get on with some C programming…

Really simple unit testing for C

Several years ago I found myself needing a simple way to unit test some c code I was working on. I had previously used JUnit, which was relatively new at that time. cppunit either wasn’t released yet, or was very raw, and besides, my code was straight c.

So I wrote my own.

I knew I didn’t want the complexity of the full JUnit framework, but I did want the the convenience of an object-oriented system.

The general design of this simple object-oriented c unit testing code is to keep the test harness very simple. Each class test can be run as it’s own program, allowing invocation from a shell script, or you can stack the tests like brickwork into increasingly more general c programs.

This is in contrast to the JUnit design where you have to set up more framework in advance, and you add tests within their framework.

The JUnit design is probably more powerful in the sense that it scales better.

On the other hand, mine is simple enough that you can design your own system using it as a building block. And small enough that you can very easily embed it into your code and ship it for internal testing if you like.

I’m sure there are other ways to do it.

Design of a simple unit testing class

The design is simple enough to implement as a class in either C or C++. I’ve done both, used both in production, and will compare the two approaches here. First, an overview on the general idea:

  1. In the C code, the unit test struct definition is located in the header file, making it defined for any file including the unit testing header file. It’s very simple, just a table:
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
     
    /** Each unit test builds a table that can be 
     * traversed to exercise each function in the 
     * component.
     */
    typedef struct _testfunc {
      int (*test)(void);
      const char * testname;
    } TestFunc;
  2. Here’s an example of a table from the demo code, which tests the correctness of a line segment intersection algorithm:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    TestFunc tf[] = {
      {test_vertical_cross,       "vertical_cross"       },
      {test_vertical_parallel,    "vertical_parallel"    },
      {test_endpoint_intersection,"endpoint_intersection"},
      {test_total_overlap,        "total_overlap"        },
      {test_partial_overlap,      "partial_overlap"      },
      {test_no_intersection1,     "no_intersection1"     },
      {NULL,                      ""                     }
    };

    These functions could be hashed into a red/black tree or something, but that’s too much work and too much code. It doesn’t really matter how the functions are ordered, and they’re all going to be called one after another, so a dispatch table is just fine.

  3. As you will see from the source code, it’s very simple: a loop scans the table and invokes each callback in turn, until it gets to NULL. The callbacks are boolean, which you will see in the C++ code, returning pass or fail:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    int 
    unittest(TestFunc * testfunc) {
     
        int i = 0;
        int passed = TRUE;
     
        while (testfunc[i].test != NULL) {
     
            unittest_print_header(stdout,testfunc[i].testname);
     
    	if (testfunc[i].test()) {
    	    fprintf(stdout, "Passed test_%s.\n", testfunc[i].testname);
    	} else {
    	    fprintf(stdout, "Failed test_%s.\n", testfunc[i].testname);
    	    passed = FALSE;
    	}
    	i++;
        }
     
        fprintf(stdout,"\n");
     
        return passed;
    }

    The default value in each of the test functions should be FALSE. Can you see why the default return value is TRUE in this function?

Testing for line intersection

For an example, we’ll be testing a function that determines if two line segments intersect. The code is part of a geometry component for the Discontinuous Deformation Analysis application. The idea is that we need to create geometrical blocks from collections of line segments. Line segments that cross each other need to be partitioned into pieces for use by different blocks, and segments that overlap each other need to be appropriately trimmed or deleted. There’s more to block construction than this, but these tasks are handled by the code we’re going to unit test here.

Here’s the overall plan for testing:

  1. Test for intersection
  2. Test for non-intersection
  3. Test for partial overlapping
  4. test for full overlapping

We’ll construct a set of line segments for testing each case.

Remember: unit testing cannot guarantee correctness. It can only find find situations which are specified as incorrect. The specification for correctness and incorrectness has to be determined out of band. In this case, that means drawing out a set of line segments on graph paper, picking off the endpoints, feeding them into the algorithm, and determining whether the algorithm is returning what we think it ought to be returning.

Download Simple Objected Oriented C Unit Test

Download the Object Oriented C toolkit and take a look for yourself. The code is LPGL licensed, but truthfully, I’m not that worried about it. If you find it useful, and you can show me something cool you did with it or how you extended it, I’m happy. Alternatively, I’d be happy to add any minor tweaks you might like to use back into the main code base… as long as the extensions are simple. If you want a full-blown framework, use CGreen or Boost.

More information on unit testing

These are the best links I could find on why unit testing is important:

  • JUnit.org: The original home of unit testing. You can learn a lot here.
  • cgreen is an interesting tool, but much heavier than the tool outlined in this article.
  • What’s with the these plants anyway?

    Plants are cool. I like them.

    I have plenty of spares, mostly succulents. If you’re an East Bay or San Francisco local and would like a cool plant, stop by some time get a couple. Or drop me a line and I’ll drop off a plant for you.

{ 3 comments… read them below or add one }

pankaj@c programming May 4, 2011 at 9:27 pm

Thanks sir for such a nice article.I must say nice method of unit testing with good explanation

Reply

Dennis Dillert September 9, 2011 at 2:50 pm

Hi David, I just wanted to thank you for sharing all your knowledge on the topic. I’ve been reading a few of your C tutorials and must say you have a great gift of explaining complicated topics using simple, clear and concise language. Dennis

Reply

Dave Doolin September 9, 2011 at 3:17 pm

Dennis, thanks, I need to actually finish the article, or split out the line intersection testing into its own article. That is some detailed, picky work.

Reply

Leave a Comment

CommentLuv badge

Previous post:

Next post: