unit testing guidelines
unit testing is the process of writing and regularly running
small tests that target a specific aspect of functionality. unit
tests significantly improve overall quality of code and help
capture regression errors early on in the development cycle. using
a unit testing framework simplifies the process of creating test
harnesses and suites.
the rapple team has selected cunit as our unit testing
framework. the cunit website has plenty of documentation and
examples which should be consulted in order to get to grips with
the framework. testing is a common quality concern and not the job
of a specific developer it is important that you run the entire
set of test suites periodically to check that changes you have made
to the code do not cause tests to fail and that no regression
errors have arisen.
unit tests can be run by building and executing the runner. to
build the runner simply issue make tests from the top
directory of the tarball extraction or the CVS sources. to run the
tests decide first whether you want to run the automated, basic
(default) or console runner (see cunit documentation) and issue the
runner command accordingly (see runner -h for help). the default
output of the runner is basic and looks something like the
following:
CUnit : A Unit testing framework for C.
http://cunit.sourceforge.net/
Suite: string utilities suite
Test: concatentation ... passed
Test: index of presence char ... passed
Test: index of absent char ... passed
Test: splitting ... passed
Suite: web asset interface suite
Test: remote user ... passed
Test: filename ... passed
Test: relative directory ... passed
Test: mime type ... passed
Test: source ... passed
Test: mime type supported ... passed
Test: transformable ... passed
Test: tidy output ... passed
Test: tidy error ... passed
--Run Summary: Type Total Ran Passed Failed
suites 2 2 n/a 0
tests 13 13 13 0
asserts 14 14 14 0
the following guidelines apply to unit testing within rapple
development:
- keep unit tests as simple and as focused as possible! test case
code is a little special and is different from normal application
code so try not to erect infrastructures to run a test if you can
use a static string or similar for your test.
- unit tests should be added to the test directory tree within
the rapple module. once you have written your test you should
either create a test suite in which to include it or add it to one
of the existing test suites found in the runner.c file. as a
general rule similar tests are stored together within a single file
(a good principle to follow is that the test suite initialisation
and cleanup functions are appropriate your test case - or at the
very least that calling them does not cause any harm ;)
- all test case files should be prepended with "t_" (e.g.,
"t_mytests.c") and those test cases that are related to a specific
module should share the name of that module (e.g.,
"t_strutil.c").
- whilst it is necessary to export test case names along with
initialisation and cleanup function names (so that they can be
invoked by the test runner) it is not normally the case that any
other function names be exported so please keep them static.
- use header files (prepended with "t_", e.g., "t_mytests.h" or
"t_strutil.h") to store exported function names and test data. this
makes it simple for others to get a good overview of where you are
going with your testing before jumping into the details in your
implementation file.
- test cases themselves should follow the following naming
convention: "ut_", followed by the module name (or custom name),
followed by an abbreviated description. for example if i want to
test concatenation in the strutil module then i will call it
"ut_strutil_concat" or if i want to test functionality "foo" which
does not belong to any specific module but can best be described as
"bar" then i will use "ut_foo_bar" and try to keep this close to
all the other "foo" tests. this helps everyone understand
intuitively where tests belong when they are added to the test
suites in a test runner.
|