TAP (Test Anything Protocol) is a simple protocol to report the result of a testsuite. It was initially designed for test suites of Perl modules, but developers of the Test::Harness modules have seen the potential for a more generic usage of the protocol outside of the Perl ecosystem and libraries are in development for other programming languages.

I'm writing C code and contrary to most programming langages today, there is no library to build test suites in a standard way. Java has JUnit, Perl has Test::Simple and Test::More...

Someone has developped libtap, but no one uses it (except FreeBSD developers as advertised on the site). Also, I do not like the library interface because it exports functions such as ok() or diag() which could conflict with existing code. So, I wrote my own library that I will publish one day. But that is not the point of this post.

When you have written a program conforming to the TAP, you want tools to analyse the result of the tests. And the main advantage of using a standardized protocol is to be able to use generic tools and avoid to implement/test/debug them yourself. The problem with TAP is that the only tool that is available is prove and it suffers of a major flaw: it is designed to run only Perl tests.

Here is a simple TAP-compliant C program that outputs the result of a static testsuite:

#include <stdio.h>

int main(int argc, char *argv[])
  puts("1..1\nok 1");
  return 0;

And the output:

$ gcc a.c
$ ./a.out
ok 1

When trying to run it with prove, perl complains it did not found Perl code:

$ prove a.out
a....Unrecognized character \x7F at a.out line 1.
        Test returned status 9 (wstat 2304, 0x900)
FAILED--1 test script could be run, alas--no output ever seen

So I wrote the following generic Perl wrapper a.out.t that just runs a.out:

# vim:set ft=perl:

use strict;
use File::Spec;
my $exe = File::Spec->rel2abs($0);
$exe =~ s/\.t$//;

exec $exe $exe or die "$exe: $!";

And now, success is achieved:

$ prove a.out.t
All tests successful.
Files=1, Tests=1,  0 wallclock secs ( 0.01 cusr +  0.01 csys =  0.02 CPU)