1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
|
.Dd December 20, 2004
.Os
.Dt TAP 3
.Sh NAME
.Nm tap
.Nd write tests that implement the Test Anything Protocol
.Sh SYNOPSIS
.In tap.h
.Sh DESCRIPTION
The
.Nm
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.
.Ss PRINTF STRINGS
In the descriptions that follow, for any function that takes as the
last two parameters
.Dq Fa char * , Fa ...
it can be assumed that the
.Fa char *
is a
.Fn printf
-like format string, and the optional arguments are values to be placed
in that string.
.Ss TEST PLANS
.Bl -tag -width indent
.It Xo
.Ft int
.Fn plan_tests "unsigned int"
.Xc
.It Xo
.Ft int
.Fn plan_no_plan "void"
.Xc
.It Xo
.Ft int
.Fn plan_skip_all "char *" "..."
.Xc
.El
.Pp
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.
.Pp
To do this, use
.Fn plan_tests ,
which always returns 0. The function will cause your program to exit
prematurely if you specify 0 tests.
.Pp
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
.Fn plan_tests
parameter every time you make a change. For those situations use
.Fn plan_no_plan .
It returns 0, and indicates to the test harness that an indeterminate number
of tests will be run.
.Pp
Both
.Fn plan_tests
and
.Fn plan_no_plan
will cause your test program to exit prematurely with a diagnostic
message if they are called more than once.
.Pp
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
.Fn plan_skip_all ,
passing as parameters a string to display indicating the reason for skipping
the tests.
.Ss SIMPLE TESTS
.Bl -tag -width indent
.It Xo
.Ft unsigned int
.Fn ok "expression" "char *" "..."
.Xc
.It Xo
.Ft unsigned int
.Fn ok1 "expression"
.Xc
.It Xo
.Ft unsigned int
.Fn pass "char *" "..."
.Xc
.It Xo
.Ft unsigned int
.Fn fail "char *" "..."
.Xc
.El
.Pp
Tests are implemented as expressions checked by calls to the
.Fn ok
and
.Fn ok1
macros. In both cases
.Fa expression
should evaluate to true if the test succeeded.
.Pp
.Fn ok
allows you to specify a name, or comment, describing the test which will
be included in the output.
.Fn ok1
is for those times when the expression to be tested is self
explanatory and does not need an associated comment. In those cases
the test expression becomes the comment.
.Pp
These four calls are equivalent:
.Bd -literal -offset indent
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 */
.Ed
.Pp
It is good practice to ensure that the test name describes the meaning
behind the test rather than what you are testing. Viz
.Bd -literal -offset indent
ok(db != NULL, "db is not NULL"); /* Not bad, but */
ok(db != NULL, "Database conn. succeeded"); /* this is better */
.Ed
.Pp
.Fn ok
and
.Fn ok1
return 1 if the expression evaluated to true, and 0 if it evaluated to
false. This lets you chain calls from
.Fn ok
to
.Fn diag
to only produce diagnostic output if the test failed. For example, this
code will include diagnostic information about why the database connection
failed, but only if the test failed.
.Bd -literal -offset indent
ok(db != NULL, "Database conn. succeeded") ||
diag("Database error code: %d", dberrno);
.Ed
.Pp
You also have
.Fn pass
and
.Fn fail .
From the Test::More documentation:
.Bd -literal -offset indent
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.
.Ed
.Pp
These are synonyms for ok(1, ...) and ok(0, ...).
.Ss SKIPPING TESTS
.Bl -tag -width indent
.It Xo
.Ft int
.Fn skip "unsigned int" "char *" "..."
.Xc
.It Xo
.Fn skip_start "expression" "unsigned int" "char *" "..."
.Xc
.It Xo
.Sy skip_end
.Xc
.El
.Pp
Sets of tests can be skipped. Ordinarily you would do this because
the test can't be run in this particular testing environment.
.Pp
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
.Fn skip )
is correct for the number of tests to skip.
.Pp
One way of implementing this is with a
.Dq do { } while(0);
loop, or an
.Dq if( ) { } else { }
construct, to ensure that there are no additional side effects from the
skipped tests.
.Bd -literal -offset indent
if(getuid() != 0) {
skip(1, "because test only works as root");
} else {
ok(do_something_as_root() == 0, "Did something as root");
}
.Ed
.Pp
Two macros are provided to assist with this. The previous example could
be re-written as follows.
.Bd -literal -offset indent
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 */
.Ed
.Ss MARKING TESTS AS Dq TODO
.Bl -tag -width indent
.It Xo
.Ft void
.Fn todo_start "char *" "..."
.Xc
.It Xo
.Ft void
.Fn todo_end "void"
.Xc
.El
.Pp
Sets of tests can be flagged as being
.Dq 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
.Xr 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
.Dq #ifdef 0 ... #endif )
the tests.
.Bd -literal -offset indent
todo_start("dwim() not returning true yet");
ok(dwim(), "Did what the user wanted");
todo_end();
.Ed
.Pp
Should
.Fn dwim
ever start succeeding you will know about it as soon as you run the
tests. Note that
.Em unlike
the
.Fn skip_*
family, additional code between
.Fn todo_start
and
.Fn todo_end
.Em is
executed.
.Ss SKIP vs. TODO
From the Test::More documentation;
.Bd -literal -offset indent
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).
.Ed
.Ss DIAGNOSTIC OUTPUT
.Bl -tag -width indent
.It Xo
.Fr unsigned int
.Fn diag "char *" "..."
.Xc
.El
.Pp
If your tests need to produce diagnostic output, use
.Fn diag .
It ensures that the output will not be considered by the TAP test harness.
.Fn diag
adds the necessary trailing
.Dq \en
for you.
.Bd -literal -offset indent
diag("Expected return code 0, got return code %d", rcode);
.Ed
.Pp
.Fn diag
always returns 0.
.Ss EXIT STATUS
.Bl -tag -width indent
.It Xo
.Fr int
.Fn exit_status void
.Xc
.El
.Pp
For maximum compatability your test program should return a particular
exit code. This is calculated by
.Fn exit_status
so it is sufficient to always return from
.Fn main
with either
.Dq return exit_status();
or
.Dq exit(exit_status());
as appropriate.
.Sh EXAMPLES
The
.Pa tests
directory in the source distribution contains numerous tests of
.Nm
functionality, written using
.Nm .
Examine them for examples of how to construct test suites.
.Sh COMPATABILITY
.Nm
strives to be compatible with the Perl Test::More and Test::Harness
modules. The test suite verifies that
.Nm
is bug-for-bug compatible with their behaviour. This is why some
functions which would more naturally return nothing return constant
values.
.Pp
If the
.Lb libpthread
is found at compile time,
.Nm
.Em should
be thread safe. Indications to the contrary (and test cases that expose
incorrect behaviour) are very welcome.
.Sh SEE ALSO
.Xr Test::More 1 ,
.Xr Test::Harness 1 ,
.Xr prove 1
.Sh STANDARDS
.Nm
requires a
.St -isoC-99
compiler. Some of the
.Nm
functionality is implemented as variadic macros, and that functionality
was not formally codified until C99. Patches to use
.Nm
with earlier compilers that have their own implementation of variadic
macros will be gratefully received.
.Sh HISTORY
.Nm
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.
.Sh AUTHORS
.An "Nik Clayton" Aq nik@ngo.org.uk ,
.Aq nik@FreeBSD.org
.Pp
.Nm
would not exist without the efforts of
.An "Michael G Schwern" Aq schqern@pobox.com ,
.An "Andy Lester" Aq andy@petdance.com ,
and the countless others who have worked on the Perl QA programme.
.Sh BUGS
Ideally, 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 using
.Nm
are known.
.Bl -bullet -offset indent
.It
stdout is set to unbuffered mode after calling any of the
.Fn plan_*
functions.
.El
|