Version 1 (modified by trac, 16 years ago) ( diff )

--

[KEEP IN SYNC WITH SELF_TEST.H!]

Introduction

Self-tests as advocated by eXtreme Programming have proven to be useful. By embedding test code into modules, we can be confident that boundary cases are handled correctly and everything still works after edits. We give guidelines for their use and explain several helper mechanisms below.

Guidelines

What makes a good self-test?

  • They belong in the module being tested to ensure they are kept in sync with it.
  • It is easiest to attach them to low-level functions, e.g. ilog2, rather than verifying the module's final result (e.g. checking renderer output by comparing pictures).
  • You should cover all cases: expected failures ("does it fail as expected?"), bad inputs ("does it reject those?"), and successes ("did it have the expected result?").
  • Tests should be non-intrusive (only bother user if something fails) and very quick. This is because we run them automatically at startup, which solves the common problem of making sure they actually run.
    If the test must by definition be slow or annoying (example: wdbg_sym's stack trace), then best to disable it by default (see below for how). It can then be enabled manually after changes, and that is better than no test at all.

Example Usage

The following is a working example of a built-in self test using our facilities. Further notes below are referenced with (1) etc.

 #if SELF_TEST_ENABLED				// (1)
 namespace test {				// (2)
 
 static void test_log2()
 {
 	TEST(ilog2(0) == -1);			// (3)
 	// further test cases..
 }
 
 static void self_test()
 {
 	test_log2();
 	// further test groups..
 }
 
 RUN_SELF_TEST;					// (4)
 
 }	// namespace test
 #endif	// #if SELF_TEST_ENABLED
  1. when not enabled, self-tests are completely removed so as not to bloat the executable. for details on how to enable/disable them globally or override in single files, see self_test.h.
  1. wrapping in a namespace is optional and must be removed for C programs. it avoids possible name collisions with the module being tested.
  1. TEST *must* be used instead of debug_assert et al.! this is explained below.
  1. automatically calls your self_test function at non-local static object init time (i.e. before main is entered).

For further details, see self_test.h.

Note: See TracWiki for help on using the wiki.