Unit-testing C code with Python & swig & nose

by syoyo


I’m finding a way how to test code of lucille.

There are some testing methods

– Unit test
– Use case(functional test)
– Behaviour driven development
– Formal verification(good for testing algorithm itself)
– Model checking for monte carlo algorithm( e.g. prism )
– etc.

In this article, I’d like to talk to about how to do unit testing for C function.

There’s already good unit testing framework for C, CUnit.
But writing fixture(setup, teardown) code also in C is harder & redundant & time-consuming,
so I tried to seek a way to test C code from scripting language.

An answer I’ve convinced so far is to use Python to write fixture and swig to call C function from Python.
And more, nose enables writing python-side test code much more simpler.

Here’s my trial of C, swig, Python and nose combination for unit testing.

C code to be tested

First, let we assume unit-test functions is defined in list.h(code grabbed from lucille source).

 * simple list routine.
 * $Id: list.h,v 2004/01/06 13:57:09 syoyo Exp $

#ifndef LIST_H
#define LIST_H

#ifdef __cplusplus
extern "C" {

typedef struct _ri_list_t
	void		  *data;
	struct _ri_list_t *next;
	struct _ri_list_t *prev;
} ri_list_t;

extern ri_list_t *ri_list_new();
/* add data to last */
extern void	  ri_list_append(ri_list_t *list, void *data);


Then, write swig interface file test.i so that C functions can be callable from Python.

%module base_list
#include "memory.h"
#include "list.h"

%include "../../../../src/base/memory.h"
%include "../../../../src/base/list.h"

Provide setup.py to ease compile/link C code to make a module.

# setup.py
import distutils
from distutils.core import setup, Extension

import os

srcPath = "../../../../src/base"

srcList = [ "list.i"
          , os.path.join(srcPath, "list.c")
          , os.path.join(srcPath, "memory.c")

setup(name = "base_list",
      version = "1.0",
      ext_modules = [Extension("_base_list", sources=srcList, include_dirs = [srcPath])])


With setup.py, compiling module can be done by just typing

$ python setup.py build_ext --inplace


Python test code

Finally, write unit test code in python(test.py)
Thanks to nose, classes whose name having “test” is considered as a test,
so we don’t need to write unit test related things explicitly.

from base_list import *

import os, sys

class TestListNewIsNotNull():

    def setup(self):

    def teardown(self):

    def testListNew(self):
        l = ri_list_new()

        assert l != None

class TestListNextAfterListNewIsNull():

    def setup(self):
        self.lst = ri_list_new()

    def teardown(self):

    def test(self):
        l = ri_list_next(self.lst)

        assert l == None


Run test with nose

Functions/Classes/Directories with name having “test” is automatically executed by nose.

 $ nosetests -v
test.TestListNewIsNotNull.testListNew ... ok
test.TestListNextAfterListNewIsNull.test ... ok

Ran 2 tests in 0.008s


Sounds nice?

All codes explained above are located at,