|
NAMEtap —
write tests that implement the Test Anything Protocol
SYNOPSIS#include <tap.h>
DESCRIPTIONThetap library provides functions for writing test
scripts that produce output consistent with the Test Anything Protocol. A test
harness that parses this protocol can run these tests and produce useful
reports indicating their success or failure.
PRINTF STRINGSIn the descriptions that follow, for any function that takes as the last two parameters “char *, ...” it can be assumed that the char * is aprintf () -like
format string, and the optional arguments are values to be placed in that
string.
TEST PLANS
You must first specify a test plan. This indicates how many tests you intend to run, and allows the test harness to notice if any tests were missed, or if the test program exited prematurely. To do this, use In some situations you may not know how many tests you will be
running, or you are developing your test program, and do not want to update
the Both If your test program detects at run time that some required
functionality is missing (for example, it relies on a database connection
which is not present, or a particular configuration option that has not been
included in the running kernel) use SIMPLE TESTS
Tests are implemented as expressions checked by calls to the
These four calls are equivalent: int i = 5; ok(i == 5, "i equals 5"); /* Overly verbose */ ok(i == 5, "i equals %d", i); /* Just to demonstrate printf-like behaviour of the test name */ ok(i == 5, "i == 5"); /* Needless repetition */ ok1(i == 5); /* Just right */ It is good practice to ensure that the test name describes the meaning behind the test rather than what you are testing. Viz ok(db != NULL, "db is not NULL"); /* Not bad, but */ ok(db != NULL, "Database conn. succeeded"); /* this is better */
ok(db != NULL, "Database conn. succeeded") || diag("Database error code: %d", dberrno); You also have Sometimes you just want to say that the tests have passed. Usually the case is you've got some complicated condition that is difficult to wedge into an ok(). In this case, you can simply use pass() (to declare the test ok) or fail (for not ok). Use these very, very, very sparingly. These are synonyms for ok(1, ...) and ok(0, ...). SKIPPING TESTS
Sets of tests can be skipped. Ordinarily you would do this because the test can't be run in this particular testing environment. For example, suppose some tests should be run as root. If the test
is not being run as root then the tests should be skipped. In this
implementation, skipped tests are flagged as being ok, with a special
message indicating that they were skipped. It is your responsibility to
ensure that the number of tests skipped (the first parameter to
One way of implementing this is with a “do { } while(0);” loop, or an “if() { } else { }” construct, to ensure that there are no additional side effects from the skipped tests. if(getuid() != 0) { skip(1, "because test only works as root"); } else { ok(do_something_as_root() == 0, "Did something as root"); } Two macros are provided to assist with this. The previous example could be re-written as follows. skip_start(getuid() != 0, 1, "because test only works as root"); ok(do_something_as_root() == 0, "Did something as root"); skip_end; /* It's a macro, no parentheses */ MARKING TESTS AS “TODO”
Sets of tests can be flagged as being “TODO”. These are tests that you expect to fail, probably because you haven't fixed a bug, or finished a new feature yet. These tests will still be run, but with additional output that indicates that they are expected to fail. Should a test start to succeed unexpectedly, tools like prove(1) will indicate this, and you can move the test out of the todo block. This is much more useful than simply commenting out (or “#ifdef 0 ... #endif”) the tests. todo_start("dwim() not returning true yet"); ok(dwim(), "Did what the user wanted"); todo_end(); Should SKIP vs. TODOFrom the Test::More documentation;If it's something the user might not be able to do, use SKIP. This includes optional modules that aren't installed, running under an OS that doesn't have some feature (like fork() or symlinks), or maybe you need an Internet connection and one isn't available. If it's something the programmer hasn't done yet, use TODO. This is for any code you haven't written yet, or bugs you have yet to fix, but want to put tests in your testing script (always a good idea). DIAGNOSTIC OUTPUT
If your tests need to produce diagnostic output, use
diag("Expected return code 0, got return code %d", rcode);
EXIT STATUS
For maximum compatability your test program should return a
particular exit code. This is calculated by
EXAMPLESThe tests directory in the source distribution contains numerous tests oftap functionality, written using
tap . Examine them for examples of how to construct
test suites.
COMPATABILITYtap strives to be compatible with the Perl Test::More
and Test::Harness modules. The test suite verifies that
tap is bug-for-bug compatible with their behaviour.
This is why some functions which would more naturally return nothing return
constant values.
If the POSIX Threads Library (libpthread,
-lpthread) is found at compile time, SEE ALSOTest::More(1), Test::Harness(1), prove(1)STANDARDStap requires a ISO/IEC 9899:1999
(“ISO C99”) compiler. Some of the
tap functionality is implemented as variadic macros,
and that functionality was not formally codified until C99. Patches to use
tap with earlier compilers that have their own
implementation of variadic macros will be gratefully received.
HISTORYtap was written to help improve the quality and coverage
of the FreeBSD regression test suite, and released in the hope that others
find it a useful tool to help improve the quality of their code.
AUTHORSNik Clayton ⟨nik@ngo.org.uk⟩, ⟨nik@FreeBSD.org⟩
BUGSIdeally, running the tests would have no side effects on the behaviour of the application you are testing. However, it is not always possible to avoid them. The following side effects of usingtap are known.
Visit the GSP FreeBSD Man Page Interface. |