2 ======================================================
3 |mutest| - A simple micro unit testing framework for C
4 ======================================================
6 :Author: Leandro Lucarella
7 :Contact: llucax@gmail.com
10 :Copyright: Leandro Lucarella (2008), released under the BOLA_ license
11 :Abstract: |mutest| is a micro `unit testing`_ framework for C (with some
12 `C++ support`_). It's mostly an idea (it even comes with
13 2 implementations_ of the idea!) with the goal of being easy to use
14 (just write your `test cases`_ grouped in `test suites`_ and you're
15 set) and so small and simple that you don't mind to copy the files to
16 your project and just use it (i.e., no dependencies).
18 The idea is simple: a source file is a `test suite`_, a function is
19 a `test case`_ (special functions can be used for `test suite`_
20 initialization_ and termination_), which can can have several checks_.
21 Checks_ comes in 2 flavors, one that only prints an error, and one that
22 terminates the current `test case`_ too. A (normally) automated `test
23 program`_ run all the `test suites`_ and print some stats. It fails
24 (returns non-zero) if any `test suite`_ fails.
34 Download the `latest distribution tarball`__ and uncompress it.
36 __ http://proj.llucax.com.ar/home/mutest/releases/mutest.tar.gz
38 You can also download any release from the `releases directory`__ or get it
39 using Git_ directly from the `Git repository`__.
41 __ http://proj.llucax.com.ar/home/mutest/releases/
42 __ http://git.llucax.com.ar/w/software/mutest.git
44 You can get `this manual`__ too, or a `PDF version`__ of it.
46 __ http://proj.llucax.com.ar/home/mutest/manual.html
47 __ http://proj.llucax.com.ar/home/mutest/manual.pdf
49 To actually install |mutest| run::
53 Default installation path is ``/usr/local`` (because of that, you'll probably
54 need superuser privileges to install to the default location). You can override
55 that by passing the ``prefix`` make variable, for example::
57 $ make prefix=/opt/mutest install
59 If you want to install just the docs, you can do::
63 Or even ``install-readme``, ``install-html`` or ``install-pdf`` if you are too
66 If you want to install just one particular implementation_, to can use the
67 ``install-c`` and ``install-py`` targets.
73 You can find some samples in the sample__ directory.
75 __ http://git.llucax.com.ar/w/software/mutest.git?a=tree;f=sample;h=d8ad4dd9c3428fef5963107c82ab6a5e34ec6e00;hb=HEAD
77 This is an example taken from there. A simple *module* called `factorial.c`_
78 with its corresponding `test suite`_ (`factorial_test.c`_).
80 You can see some `C++ support`_ in the `exception_test.cpp`_ `test suite`_.
85 .. include:: sample/factorial.c
91 .. include:: sample/factorial_test.c
97 .. include:: sample/exception_test.cpp
104 |mutest| is about 4 simple concepts: `test program`_, `test suite`_, `test
105 case`_ and checks_. Well, to be honest you probably will need `test suite`_
106 initialization_ and termination_ too =)
112 A **test program** is the higher level unit of |mutest|. The test program is
113 the one in charge of running all your tests. Probably one of the more important
114 features of |mutest| is that you are not supposed to bother about the test
115 program. So, different implementations_ have different ways to tackle this.
116 Some need more or less interactions from your part, and each have their pros
119 But this is all you need to know for now, for more details see how the test
120 program is implemented by your implementation_ of choice.
126 A **test suite** is the higher level unit of |mutest| that you should
127 care about =). Is not much more than a way to group `test cases`_. Code-wise,
128 a test suite is a C (or C++) module (or compilation unit). Not clear enough?
129 A unit test is an object file (could be a shared object depending on the
130 implementation_). This module should have one or more `test cases`_ and it
131 could have any number (including zero) of initialization_ and termination_
134 A test suite, is inspected by the `test program`_ for `test cases`_ and
135 initialization_ and termination_ functions, and run them.
137 A test suite fail if one or more `test cases`_ fail, and it's skipped if one or
138 more initialization_ functions fail (or, depending on the implementation, if
139 the test suite can't be loaded at all).
145 A **test case** is just a plain function with a special signature and name.
146 A test case function name must start with ``mu_test``, and take no arguments
147 and return nothing. For example::
149 void mu_test_something(void);
151 A test case (probably) only make sense if it has checks_. A test case succeed
152 only if all its checks succeed too.
154 Test are executed in an implementation_-dependant order, but usually the
155 default order is alphabetical.
161 Checks are assertions that a `test case`_ must pass (a boolean expression that
162 must evaluate to *true*). There are 2 big flavors of checks: **check** and
163 **ensure**. **check** just print an error (and *mark* the `test case`_ as
164 failed) and **ensure** halt the `test case`_ execution, jumping to the next
167 For better `C++ support`_ there are check macros that assert that a specified
168 exception is thrown (instead of check for a boolean expression to evaluate to
171 You can take a look at the reference_ to see the different flavors of check
172 macros in more detail.
178 Sometimes you need to setup some environment shared between all the `test
179 cases`_ in a `test suite`_. You can use **initialization functions** for this.
181 An initialization function, like a `test case`_, is a plain C function with
182 a special name and signature. The name must start with ``mu_init`` and it must
183 take no arguments, and return an *error code* (``0`` being success). For
186 int mu_init_something(void);
188 All initialization functions are executed before any `test case`_, in an
189 implementation_-dependant order, and if one of them fail (returns non-zero),
190 the whole `test suite`_ is skipped immediately.
196 **Termination functions** are just like initialization_ functions, but they're
197 executed **after** the `test cases`_, their names start with ``mu_term`` and
198 they return nothing. For example::
200 void mu_term_something(void);
206 You can use |mutest| with C++, the only care you must take is that, because of
207 C++ `name mangling`_ (and |mutest| relaying on function names), you must
208 declare your `test cases`_ and initialization_ and termination_ functions as
209 ``extern "C"`` (see `exception_test.cpp`_ for an example).
211 Checks_ become *exception-safe* when using |mutest| with a C++ compiler, and
212 2 extra checks_ designed for C++ get defined (`mu_echeck()`_ and
213 `mu_eensure()`_). They assert that an expression throws a particular exception.
219 There are 2 big groups of possible implementations that I can think
220 of: *static* and *dynamic*.
222 |mutest| comes with one implementation of each group.
225 Static Implementations
226 ----------------------
228 Static implementations can be only written in C/C++ (or other language that is
229 link-compatible with C, like the `D Programming Language`_, but since one of
230 the main goals of |mutest| is avoid unnecessary dependencies, you probably
231 don't want to depend on an extra language/compiler to run your tests =).
233 The main advantage is better debugging support, because you can run the `test
234 program`_ in a standard debugger and see what happens with `test cases`_ very
237 The main disadvantage is, the `test suites`_ must be figured out in
238 *compile-time*, usually using some kind of code generation (if you want to
239 avoid writing repetitive code yourself). There's also a limitation in the `test
240 case`_, initialization_ and termination_ functions names: they should be unique
241 for all the `test program`_.
247 |mutest| comes with a C static implementation. Only 3 files are needed:
248 ``mutest.c`` (the *user-independent* part of the `test program`_), ``mkmutest``
249 (a bash script for generating the *user-dependent* part of the `test program`_)
250 and ``mutest.h`` (the header file that `test suites`_ should include).
252 You can copy this 3 files to your project or install them at system-level and
255 The procedure is simple, You should compile you `test suites`_, ``mutest.c``
256 and the generated output of ``mkmutest`` as object files and link them
261 $ cc -c -o mutest.o mutest.c
262 $ cc -c -o test1.o test1.c
263 $ cc -c -o test2.o test2.c
264 $ mkmutest mutest.h test1.o test2.o | cc -xc -c -o runmutest.o -
265 $ cc -o testprg mutest.o test1.o test2.o runmutest.o
267 Then you can run the `test program`_ invoking it with no arguments::
272 ``mkmutest`` Invocation
273 """""""""""""""""""""""
275 This small script take 1 mandatory positional argument: the path to the
276 ``mutest.h`` file. All remaining positional arguments should be object files
277 representing `test suites`_.
280 Test Program Invocation
281 """""""""""""""""""""""
283 The test program can be invoked without arguments, but can take some extra
287 Be verbose. This is accumulative, when you add extra ``-v`` you will
290 By default, you just get failed checks_ printed. If you use a single
291 ``-v``, a summary of failed/passed `test suites`_, `test cases`_ and
292 checks_ will be printed. If an extra ``-v`` is used, you'll see the current
293 `test suite`_ being executed. Another ``-v`` and you'll get the current
294 `test case`_, and another one, and you'll get each check_.
300 Even when dependencies are kept minimal, there always be a few ;)
302 To use this implementation you just need:
304 * A C compiler (you already needed that, so...)
305 * The ``nm`` program (from `GNU Binutils`_, included in virtually any \*NIX)
306 * The `GNU Bash`_ shell interpreter (also included in virtually any \*NIX)
309 Dynamic Implementations
310 -----------------------
312 Dynamic implementations, on the other hand, can be written in any language that
313 can access to shared objects. The idea is to inspect a shared object for `test
314 suites`_ and run them, without requiring any information about `test suites`_
317 There are several advantages in this kind of implementations. The dynamic
318 nature let you completely separate the `test program`_ from the user-written
319 `test suites`_ and you can choose at *run-time* what `test suites`_ to execute
320 by just selecting the correct shared objects. Also, `test case`_,
321 initialization_ and termination_ functions names only have to be unique in the
322 scope of the `test suites`_, because `test suites`_ are completely isolated in
323 separate shared objects.
325 But everything comes at a price, and the higher price to pay is
326 *debuggability*. It's a little harder to plug a debugger to a shared object.
329 Python implementation
330 ~~~~~~~~~~~~~~~~~~~~~
332 This implementation is much simpler and elegant than the `C implementation`_.
333 Only 2 files are needed: ``mutest`` (`test program`_ written in Python_ using
334 ctypes_ module to access the shared object symbols) and ``mutest.h`` (the
335 header file that `test suites`_ should include).
337 Since both implementations provided by |mutest| share the same ``mutest.h``,
338 you should define the ``MUTEST_PY`` macro when compiling the `test suites`_ if
339 you will run them using this implementation.
341 As with the `C implementation`_, you can copy this 2 files to your project or
342 install them at system-level and use them globally.
344 The procedure is even simpler than the `C implementation`_: compile and link
345 you `test suites`_ as shared objects and then run the ``mutest`` program
346 passing the shared objects as arguments. For example::
348 $ cc -c -fPIC -DMUTEST_PY -o test1.o test1.c
349 $ cc -shared -o test1.so test1.o
350 $ cc -c -fPIC -DMUTEST_PY -o test2.o test2.c
351 $ cc -shared -o test2.so test2.o
352 $ mutest test1.so test2.so
356 ``mutest`` Invocation
357 """""""""""""""""""""
359 ``mutest`` program takes `test suites`_ shared objects to run as positional
360 arguments. It accepts the same options as the `C implementation's test
361 program`__ and some extra options are accepted too:
367 Be quiet (no output is shown at all).
370 Search for `test suites`_ (\*.so) in the current directory and add them
371 to the list of `test suites`_ to run.
374 Show a help message and exit.
376 __ `Test Program Invocation`_
382 As with the `C implementation`_, some minor dependencies are needed:
384 * Python_ (2.5 or later)
385 * The ``nm`` program (from `GNU Binutils`_, included in virtually any \*NIX)
387 You will need a C compiler for building the `test suites`_ too, but technically
388 is not needed by |mutest| itself ;)
398 ``mu_check(expression)``
401 Check that the ``expression`` evaluates to *true*. Continue with the
402 `test case`_ if fail.
412 mu_check(5 == 4); /* fail */
413 mu_check(5 == 5); /* excecuted, pass */
421 ``mu_ensure(expression)``
424 Check that the ``expression`` evaluates to *true*. Interrupt the `test
435 mu_ensure(5 == 4); /* fail */
436 mu_check(5 == 5); /* not excecuted */
444 ``mu_echeck(class, expression)``
447 Check that the ``expression`` throws a specific exception ``class`` (or
448 subclass). Continue with the `test case`_ if fail.
462 mu_echeck(std::exception, true); /* fail */
463 mu_echeck(std::exception,
464 throw std::runtime_error("!")); /* excecuted, pass */
472 ``mu_eensure(class, expression)``
475 Check that the ``expression`` throws a specific exception ``class`` (or
476 subclass). Interrupt the `test case`_ if fail.
490 mu_eensure(std::exception, true); /* fail */
491 mu_echeck(std::exception,
492 throw std::runtime_error("!")); /* not excecuted */
500 This manual was written using reStructuredText_.
502 .. Use section numbers
506 .. Internal Links (aliases):
507 .. _`test suites`: `test suite`_
508 .. _`test cases`: `test case`_
510 .. _implementation: implementations_
514 .. _BOLA: http://blitiri.com.ar/p/bola/
515 .. _`unit testing`: http://en.wikipedia.org/wiki/Unit_testing
516 .. _`name mangling`: http://en.wikipedia.org/wiki/Name_mangling
517 .. _`D Programming Language`: http://www.digitalmars.com/d/
518 .. _`GNU Binutils`: http://www.gnu.org/software/binutils/
519 .. _`GNU Bash`: http://www.gnu.org/software/bash/
520 .. _Python: http://www.python.org/
521 .. _ctypes: http://docs.python.org/library/ctypes.html
522 .. _reStructuredText: http://docutils.sourceforge.net/rst.html
523 .. _Git: http://git.or.cz/
527 .. |mutest| replace:: *mutest*
530 .. vim: set filetype=rst expandtab shiftwidth=4 softtabstop=4 :