Since we are creating a library to handle money, we will first create an interface in money.h, an implementation in money.c, and a place to store our unit tests, check_money.c. We want to integrate these core files into our build system, and will need some additional structure. To manage everything we'll use Autoconf, Automake, and friends (collectively known as Autotools) for this example. One could do something similar with ordinary Makefiles, but in the authors' opinion, it is generally easier to use Autotools than bare Makefiles, and they provide built-in support for running tests.
Note that this is not the place to explain how Autotools works. If you need help understanding what's going on beyond the explanations here, the best place to start is probably Alexandre Duret-Lutz's excellent Autotools tutorial.
The examples in this section are part of the Check distribution; you don't need to spend time cutting and pasting or (worse) retyping them. Locate the Check documentation on your system and look in the example directory. The standard directory for GNU/Linux distributions should be /usr/share/doc/check/example. This directory contains the final version reached the end of the tutorial. If you want to follow along, create backups of money.h, money.c, and check_money.c, and then delete the originals.
We set up a directory structure as follows:
.
|-- Makefile.am
|-- README
|-- configure.ac
|-- src
| |-- Makefile.am
| |-- main.c
| |-- money.c
| `-- money.h
`-- tests
|-- Makefile.am
`-- check_money.c
Note that this is the output of tree, a great directory visualization tool. The top-level Makefile.am is simple; it merely tells Automake how to process subdirectories:
SUBDIRS = src . tests
Note that tests comes last, because the code should be testing
an already compiled library. configure.ac is standard Autoconf
boilerplate, as specified by the Autotools tutorial and as suggested
by autoscan. The AM_PATH_CHECK() is the only line
particular to Check see AM_PATH_CHECK.
src/Makefile.am builds libmoney as a Libtool archive,
and links it to an application simply called main. The
application's behaviour is not important to this tutorial; what's
important is that none of the functions we want to unit test appear in
main.c; this probably means that the only function in
main.c should be main() itself. In order to test the
whole application, unit testing is not appropriate: you should use a
system testing tool like Autotest. If you really want to test
main() using Check, rename it to something like
_myproject_main() and write a wrapper around it.
The primary build instructions for our unit tests are in tests/Makefile.am:
## Process this file with automake to produce Makefile.in
TESTS = check_money
check_PROGRAMS = check_money
check_money_SOURCES = check_money.c $(top_builddir)/src/money.h
check_money_CFLAGS = @CHECK_CFLAGS@
check_money_LDADD = @CHECK_LIBS@ $(top_builddir)/src/libmoney.la
TESTS tells Automake which test programs to run for
make check. Similarly, the check_ prefix in
check_PROGRAMS actually comes from Automake; it says to build
these programs only when make check is run. (Recall that
Automake's check target is the origin of Check's name.) The
check_money test is a program that we will build from
tests/check_money.c, linking it against both
src/libmoney.la and the installed libcheck.la on our
system. The appropriate compiler and linker flags for using Check are
found in @CHECK_CFLAGS@ and @CHECK_LIBS@, values
defined by the AM_PATH_CHECK macro.
Now that all this infrastructure is out of the way, we can get on with development. src/money.h should only contain standard C header boilerplate:
#ifndef MONEY_H
#define MONEY_H
#endif /* MONEY_H */
src/money.c should be empty, and tests/check_money.c
should only contain an empty main() function:
int
main (void)
{
return 0;
}
Create the GNU Build System for the project and then build main and libmoney.la as follows:
$ autoreconf --install
$ ./configure
$ make
(autoreconf determines which commands are needed in order for configure to be created or brought up to date. Previously one would use a script called autogen.sh or bootstrap, but that practice is unnecessary now.)
Now build and run the check_money test with make check. If all goes well, make should report that our tests passed. No surprise, because there aren't any tests to fail. If you have problems, make sure to see AM_PATH_CHECK.
This was tested on the i386 “testing” distribution of Debian GNU/Linux (etch) in March 2006, using Autoconf 2.59, Automake 1.9.6, and Libtool 1.5.22. Please report any problems to check-devel@lists.sourceforge.net.