~ubuntu-branches/ubuntu/trusty/bash-completion/trusty-updates

« back to all changes in this revision

Viewing changes to doc/testing.txt

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2012-07-23 16:07:59 UTC
  • mfrom: (5.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20120723160759-lt9vn33dl3nak9l0
Tags: 1:2.0-1ubuntu1
* debian/maintscript, debian/postinst:
  - clean etc conffiles on upgrade since completion files are in /usr
    with the new version
* Resync with Debian, remaining diff
  * debian/patches/disable-avahi-browse.diff: Disable avahi-browse since
    it scales poorly in the current form: refresh patch
  * patches/101_bash_completion.oga_ogv.patch: Increase support for other
    OGG formats including .oga, .ogx, etc. (LP: #311525)
  * patches/103_colormake.patch: Add support for colormake to the make
    completion rules. (LP: #743208)
* Dropped changes:
  * Add conffile upgrade handling for a run of conffiles that were dropped
    since lucid: lucid upgrades are only supported to precise.
* Those fixes are in the new version
  * debian/patches/apt-get-changelog.patch:
  * Drop whitelists if they fail to produce any results:
  * patches/apt-get-download.patch: Add download as an apt-get
    sub-command (LP: #720541)
  * patches/102_manpager.patch: Override MANPAGER when generating perldoc
    completions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Automated testing
 
2
=================
 
3
 
 
4
Introduction
 
5
------------
 
6
The bash-completion package contains an automated test suite.  Running the
 
7
tests should help verifying that bash-completion works as expected.  The tests
 
8
are also very helpful in uncovering software regressions at an early stage.
 
9
 
 
10
The bash-completion test suite is written on top of the
 
11
http://www.gnu.org/software/dejagnu/[DejaGnu] testing framework.  DejaGnu is
 
12
written in http://expect.nist.gov[Expect], which in turn uses
 
13
http://tcl.sourceforge.net[Tcl] -- Tool command language.
 
14
 
 
15
 
 
16
Coding Style Guide
 
17
------------------
 
18
 
 
19
The bash-completion test suite tries to adhere to this
 
20
http://wiki.tcl.tk/708[Tcl Style Guide].
 
21
 
 
22
 
 
23
Installing dependencies
 
24
-----------------------
 
25
 
 
26
Installing dependencies should be easy using your local package manager.
 
27
 
 
28
 
 
29
Debian/Ubuntu
 
30
~~~~~~~~~~~~~
 
31
 
 
32
On Debian/Ubuntu you can use `apt-get`:
 
33
-------------
 
34
sudo apt-get install dejagnu tcllib
 
35
-------------
 
36
This should also install the necessary `expect` and `tcl` packages.
 
37
 
 
38
Fedora/RHEL/CentOS
 
39
~~~~~~~~~~~~~~~~~~
 
40
 
 
41
On Fedora and RHEL/CentOS (with EPEL) you can use `yum`:
 
42
-------------
 
43
sudo yum install dejagnu tcllib
 
44
-------------
 
45
This should also install the necessary `expect` and `tcl` packages.
 
46
 
 
47
 
 
48
 
 
49
Structure
 
50
---------
 
51
 
 
52
 
 
53
Main areas (DejaGnu tools)
 
54
~~~~~~~~~~~~~~~~~~~~~~~~~~
 
55
 
 
56
The tests are grouped into different areas, called _tool_ in DejaGnu:
 
57
 
 
58
*completion*::
 
59
  Functional tests per completion.
 
60
*install*:: 
 
61
  Functional tests for installation and caching of the main bash-completion
 
62
  package.
 
63
*unit*:: 
 
64
  Unit tests for bash-completion helper functions.
 
65
 
 
66
Each tool has a slightly different way of loading the test fixtures, see
 
67
<<Test_context,Test context>> below.
 
68
 
 
69
 
 
70
Completion
 
71
~~~~~~~~~~
 
72
 
 
73
Completion tests are spread over two directories: `completion/\*.exp` calls
 
74
completions in `lib/completions/\*.exp`.  This two-file system stems from
 
75
bash-completion-lib (http://code.google.com/p/bash-completion-lib/, containing
 
76
dynamic loading of completions) where tests are run twice per completion; once
 
77
before dynamic loading and a second time after to confirm that all dynamic
 
78
loading has gone well.
 
79
 
 
80
For example:
 
81
 
 
82
----
 
83
set test "Completion via comp_load() should be installed"
 
84
set cmd "complete -p awk"
 
85
send "$cmd\r"
 
86
expect {
 
87
    -re "^$cmd\r\ncomplete -o filenames -F comp_load awk\r\n/@$" { pass "$test" }
 
88
    -re /@ { fail "$test at prompt" }
 
89
}
 
90
 
 
91
 
 
92
source "lib/completions/awk.exp"
 
93
 
 
94
 
 
95
set test "Completion via _longopt() should be installed"
 
96
set cmd "complete -p awk"
 
97
send "$cmd\r"
 
98
expect {
 
99
    -re "^$cmd\r\ncomplete -o filenames -F _longopt awk\r\n/@$" { pass "$test" }
 
100
    -re /@ { fail "$test at prompt" }
 
101
}
 
102
 
 
103
 
 
104
source "lib/completions/awk.exp"
 
105
----
 
106
 
 
107
Looking to the completion tests from a broader perspective, every test for a
 
108
command has two stages which are now reflected in the two files:
 
109
 
 
110
. Tests concerning the command completions' environment (typically in
 
111
`test/completion/foo`)
 
112
. Tests invoking actual command completion (typically in
 
113
`test/lib/completions/foo`)
 
114
 
 
115
 
 
116
Running the tests
 
117
-----------------
 
118
 
 
119
The tests are run by calling `runtest` command in the test directory:
 
120
-----------------------
 
121
runtest --outdir log --tool completion
 
122
runtest --outdir log --tool install
 
123
runtest --outdir log --tool unit
 
124
-----------------------
 
125
The commands above are already wrapped up in shell scripts within the `test`
 
126
directory:
 
127
-----------------------
 
128
./runCompletion
 
129
./runInstall
 
130
./runUnit
 
131
-----------------------
 
132
To run a particular test, specify file name of your test as an argument to
 
133
`runCompletion` script:
 
134
-----------------------
 
135
./runCompletion ssh.exp
 
136
-----------------------
 
137
That will run `test/completion/ssh.exp`.
 
138
 
 
139
 
 
140
Running tests via cron
 
141
~~~~~~~~~~~~~~~~~~~~~~
 
142
 
 
143
The test suite requires a connected terminal (tty).  When invoked via cron, no
 
144
tty is connected and the test suite may respond with this error:
 
145
---------------------------------------------
 
146
can't read "multipass_name": no such variable
 
147
---------------------------------------------
 
148
 
 
149
To run the tests successfully via cron, connect a terminal by redirecting
 
150
stdin from a tty, e.g. /dev/tty40.  (In Linux, you can press alt-Fx or
 
151
ctrl-alt-Fx to switch the console from /dev/tty1 to tty7.  There are many more
 
152
/dev/tty* which are not accessed via function keys.  To be safe, use a tty
 
153
greater than tty7)
 
154
 
 
155
----------------------
 
156
./runUnit < /dev/tty40
 
157
----------------------
 
158
 
 
159
If the process doesn't run as root (recommended), root will have to change the
 
160
owner and permissions of the tty:
 
161
-------------------------
 
162
sudo chmod o+r /dev/tty40
 
163
-------------------------
 
164
 
 
165
To make this permission permanent (at least on Debian) - and not revert back on
 
166
reboot - create the file `/etc/udev/rules.d/10-mydejagnu.rules`, containing:
 
167
----------------------------
 
168
KERNEL=="tty40", MODE="0666"
 
169
----------------------------
 
170
 
 
171
To start the test at 01:00, set the crontab to this:
 
172
----------------------------
 
173
* 1 * * * cd bash-completion/test && ./cron.sh < /dev/tty40
 
174
----------------------------
 
175
 
 
176
Here's an example batch file `cron.sh`, to be put in the bash-completion `test`
 
177
directory.  This batch file only e-mails the output of each test-run if the
 
178
test-run fails.
 
179
 
 
180
[source,bash]
 
181
---------------------------------------------------------------------
 
182
#!/bin/sh
 
183
 
 
184
set -e  # Exit if simple command fails
 
185
set -u  # Error if variable is undefined
 
186
 
 
187
CRON=running
 
188
LOG=/tmp/bash-completion.log~
 
189
 
 
190
    # Retrieve latest sources
 
191
git pull
 
192
 
 
193
    # Run tests on bash-4
 
194
 
 
195
./runUnit --outdir log/bash-4 --tool_exec /opt/bash-4.0/bin/bash > $LOG || cat $LOG
 
196
./runCompletion --outdir log/bash-4 --tool_exec /opt/bash-4.0/bin/bash > $LOG || cat $LOG
 
197
 
 
198
    # Clean up log file
 
199
[ -f $LOG ] && rm $LOG
 
200
---------------------------------------------------------------------
 
201
 
 
202
Specifying bash binary
 
203
~~~~~~~~~~~~~~~~~~~~~~
 
204
 
 
205
The test suite standard uses `bash` as found in the tcl path (/bin/bash).
 
206
Using `--tool_exec` you can specify which bash binary you want to run the test
 
207
suite against, e.g.:
 
208
 
 
209
----------------
 
210
./runUnit --tool_exec /opt/bash-4.0/bin/bash
 
211
----------------
 
212
 
 
213
 
 
214
 
 
215
 
 
216
Maintenance
 
217
-----------
 
218
 
 
219
 
 
220
Adding a completion test
 
221
~~~~~~~~~~~~~~~~~~~~~~~~
 
222
 
 
223
You can run `cd test && ./generate cmd` to add a test for the `cmd` command.
 
224
This will add two files with a very basic tests:
 
225
----------------------------------
 
226
test/completion/cmd.exp
 
227
test/lib/completions/cmd.exp
 
228
----------------------------------
 
229
Place any additional tests into `test/lib/completions/cmd.exp`.
 
230
 
 
231
 
 
232
Fixing a completion test
 
233
~~~~~~~~~~~~~~~~~~~~~~~~
 
234
Let's consider this real-life example where an ssh completion bug is fixed.
 
235
First you're triggered by unsuccessful tests:
 
236
 
 
237
----------------------------------
 
238
$ ./runCompletion
 
239
...
 
240
        === completion Summary ===
 
241
 
 
242
# of expected passes        283
 
243
# of unexpected failures    8
 
244
# of unresolved testcases   2
 
245
# of unsupported tests      47
 
246
----------------------------------
 
247
 
 
248
Take a look in `log/completion.log` to find out which specific command is
 
249
failing.
 
250
 
 
251
-----------------------
 
252
$ vi log/completion.log
 
253
-----------------------
 
254
 
 
255
Search for `UNRESOLVED` or `FAIL`.  From there scroll up to see which `.exp`
 
256
test is failing:
 
257
 
 
258
---------------------------------------------------------
 
259
/@Running ./completion/ssh.exp ...
 
260
...
 
261
UNRESOLVED: Tab should complete ssh known-hosts at prompt
 
262
---------------------------------------------------------
 
263
 
 
264
In this case it appears `ssh.exp` is causing the problem.  Isolate the `ssh`
 
265
tests by specifying just `ssh.exp` to run.  Furthermore add the `--debug` flag,
 
266
so output gets logged in `dbg.log`:
 
267
 
 
268
----------------------------------
 
269
$ ./runCompletion ssh.exp --debug
 
270
...
 
271
        === completion Summary ===
 
272
 
 
273
# of expected passes        1
 
274
# of unresolved testcases   1
 
275
----------------------------------
 
276
 
 
277
Now we can have a detailed look in `dbg.log` to find out what's going wrong.
 
278
Open `dbg.log` and search for `UNRESOLVED` (or `FAIL` if that's what you're
 
279
looking for):
 
280
 
 
281
---------------------------------------------------------
 
282
UNRESOLVED: Tab should complete ssh known-hosts at prompt
 
283
---------------------------------------------------------
 
284
 
 
285
From there, search up for the first line saying: 
 
286
 
 
287
-------------------------------------------------
 
288
expect: does "..." match regular expression "..."
 
289
-------------------------------------------------
 
290
 
 
291
This tells you where the actual output differs from the expected output.  In
 
292
this case it looks like the test "ssh -F fixtures/ssh/config <TAB>" is
 
293
expecting just hostnames, whereas the actual completion is containing commands
 
294
- but no hostnames.
 
295
So what should be expected after "ssh -F fixtures/ssh/config <TAB>" are *both*
 
296
commands and hostnames.  This means both the test and the completion need
 
297
fixing.  Let's start with the test.
 
298
 
 
299
----------------------------
 
300
$ vi lib/completions/ssh.exp
 
301
----------------------------
 
302
 
 
303
Search for the test "Tab should complete ssh known-hosts".  Here you could've
 
304
seen that what was expected were hostnames ($hosts):
 
305
 
 
306
-----------------------------------------
 
307
set expected "^$cmd\r\n$hosts\r\n/@$cmd$"
 
308
-----------------------------------------
 
309
 
 
310
Adding *all* commands (which could well be over 2000) to 'expected', seems a
 
311
bit overdone so we're gonna change things here.  Lets expect the unit test for
 
312
`_known_hosts` assures all hosts are returned.  Then all we need to do here is
 
313
expect one host and one command, just to be kind of sure that both hosts and
 
314
commands are completed.
 
315
 
 
316
Looking in the fixture for ssh:
 
317
 
 
318
-----------------------------
 
319
$ vi fixtures/ssh/known_hosts
 
320
-----------------------------
 
321
 
 
322
it looks like we can add an additional host 'ls_known_host'.  Now if we would
 
323
perform the test "ssh -F fixtures/ssh/config ls<TAB>" both the command `ls` and
 
324
the host `ls_known_host` should come up.  Let's modify the test so:
 
325
 
 
326
--------------------------------------------------------
 
327
$ vi lib/completions/ssh.exp
 
328
...
 
329
set expected "^$cmd\r\n.*ls.*ls_known_host.*\r\n/@$cmd$"
 
330
--------------------------------------------------------
 
331
 
 
332
Running the test reveals we still have an unresolved test:
 
333
 
 
334
----------------------------------
 
335
$ ./runCompletion ssh.exp --debug
 
336
...
 
337
        === completion Summary ===
 
338
 
 
339
# of expected passes        1
 
340
# of unresolved testcases   1
 
341
----------------------------------
 
342
 
 
343
But if now look into the log file `dbg.log` we can see the completion only
 
344
returns commands starting with 'ls' but fails to match our regular expression
 
345
which also expects the hostname `ls_known_host':
 
346
 
 
347
-----------------------
 
348
$ vi dbg.log
 
349
...
 
350
expect: does "ssh -F fixtures/ssh/config ls\r\nls           lsattr       lsb_release  lshal        lshw         lsmod        lsof         lspci        lspcmcia     lspgpot      lss16toppm\r\nlsusb\r\n/@ssh -F fixtures/ssh/config ls" (spawn_id exp9) match regular expression "^ssh -F fixtures/ssh/config ls\r\n.*ls.*ls_known_host.*\r\n/@ssh -F fixtures/ssh/config ls$"? no
 
351
-----------------------
 
352
 
 
353
Now let's fix ssh completion:
 
354
 
 
355
-------------------
 
356
$ vi ../contrib/ssh
 
357
...
 
358
-------------------
 
359
 
 
360
until the test shows:
 
361
 
 
362
----------------------------------
 
363
$ ./runCompletion ssh.exp
 
364
...
 
365
        === completion Summary ===
 
366
 
 
367
# of expected passes        2
 
368
----------------------------------
 
369
 
 
370
Fixing a unit test
 
371
~~~~~~~~~~~~~~~~~~
 
372
Now let's consider a unit test failure.  First you're triggered by unsuccessful
 
373
tests:
 
374
 
 
375
----------------------------------
 
376
$ ./runUnit
 
377
...
 
378
        === unit Summary ===
 
379
 
 
380
# of expected passes        1
 
381
# of unexpected failures    1
 
382
----------------------------------
 
383
 
 
384
Take a look in `log/unit.log` to find out which specific command is failing.
 
385
 
 
386
-----------------
 
387
$ vi log/unit.log
 
388
-----------------
 
389
 
 
390
Search for `UNRESOLVED` or `FAIL`.  From there scroll up to see which `.exp`
 
391
test is failing:
 
392
 
 
393
------------------------------------------
 
394
/@Running ./unit/_known_hosts_real.exp ...
 
395
...
 
396
FAIL: Environment should stay clean
 
397
------------------------------------------
 
398
 
 
399
In this case it appears `_known_hosts_real.exp` is causing the problem.
 
400
Isolate the `_known_hosts_real` test by specifying just `_known_hosts_real.exp`
 
401
to run.  Furthermore add the `--debug` flag, so output gets logged in
 
402
`dbg.log`:
 
403
 
 
404
----------------------------------
 
405
$ ./runUnit _known_hosts_real.exp --debug
 
406
...
 
407
        === completion Summary ===
 
408
 
 
409
# of expected passes        1
 
410
# of unexpected failures    1
 
411
----------------------------------
 
412
 
 
413
Now, if we haven't already figured out the problem, we can have a detailed look
 
414
in `dbg.log` to find out what's going wrong.  Open `dbg.log` and search for
 
415
`UNRESOLVED` (or `FAIL` if that's what you're looking for):
 
416
 
 
417
-----------------------------------
 
418
FAIL: Environment should stay clean
 
419
-----------------------------------
 
420
 
 
421
From there, search up for the first line saying: 
 
422
 
 
423
-------------------------------------------------
 
424
expect: does "..." match regular expression "..."
 
425
-------------------------------------------------
 
426
 
 
427
This tells you where the actual output differs from the expected output.  In
 
428
this case it looks like the the function `_known_hosts_real` is unexpectedly
 
429
modifying global variables `cur` and `flag`.  In case you need to modify the
 
430
test:
 
431
 
 
432
-----------------------------------
 
433
$ vi lib/unit/_known_hosts_real.exp
 
434
-----------------------------------
 
435
 
 
436
Rationale
 
437
---------
 
438
 
 
439
 
 
440
Naming conventions
 
441
~~~~~~~~~~~~~~~~~~
 
442
 
 
443
Test suite or testsuite
 
444
^^^^^^^^^^^^^^^^^^^^^^^
 
445
The primary Wikipedia page is called
 
446
http://en.wikipedia.org/wiki/Test_suite[test suite] and not testsuite, so
 
447
that's what this document sticks to.
 
448
 
 
449
script/generate
 
450
^^^^^^^^^^^^^^^
 
451
The name and location of this code generation script come from Ruby on Rails'
 
452
http://en.wikibooks.org/wiki/Ruby_on_Rails/Tools/Generators[script/generate].
 
453
 
 
454
 
 
455
 
 
456
 
 
457
== Reference
 
458
 
 
459
Within test scripts the following library functions can be used:
 
460
 
 
461
[[Test_context]]
 
462
== Test context
 
463
 
 
464
The test environment needs to be put to fixed states when testing.  For
 
465
instance the bash prompt (PS1) is set to the current test directory, followed
 
466
by an at sign (@).  The default settings for `bash` reside in `config/bashrc`
 
467
and `config/inputrc`.
 
468
 
 
469
For each tool (completion, install, unit) a slightly different context is in
 
470
effect.
 
471
 
 
472
=== What happens when tests are run?
 
473
 
 
474
==== completion
 
475
 
 
476
When the completions are tested, invoking DejaGnu will result in a call to
 
477
`completion_start()` which in turn will start `bash --rcfile config/bashrc`.
 
478
 
 
479
.What happens when completion tests are run?
 
480
----
 
481
               | runtest --tool completion
 
482
               V
 
483
    +----------+-----------+
 
484
    |  lib/completion.exp  |
 
485
    |  lib/library.exp     |
 
486
    |  config/default.exp  |
 
487
    +----------+-----------+
 
488
               :
 
489
               V
 
490
    +----------+-----------+    +---------------+    +----------------+
 
491
    |  completion_start()  +<---+ config/bashrc +<---| config/inputrc |
 
492
    | (lib/completion.exp) |    +---------------+    +----------------+
 
493
    +----------+-----------+
 
494
               |                                   ,+----------------------------+
 
495
               |                               ,--+-+  "Actual completion tests" |
 
496
               V                              /   +------------------------------+
 
497
    +----------+-----------+    +-----------------------+
 
498
    |   completion/*.exp   +<---| lib/completions/*.exp | 
 
499
    +----------+-----------+    +-----------------------+ 
 
500
               |          \                        ,+--------------------------------+
 
501
               |           `----------------------+-+  "Completion invocation tests" |
 
502
               V                                  +----------------------------------+
 
503
    +----------+-----------+
 
504
    |   completion_exit()  |
 
505
    | (lib/completion.exp) |
 
506
    +----------------------+
 
507
----
 
508
Setting up bash once within `completion_start()` has the speed advantage that
 
509
bash - and bash-completion - need only initialize once when testing multiple
 
510
completions, e.g.:
 
511
----
 
512
    runtest --tool completion alias.exp cd.exp
 
513
----
 
514
==== install
 
515
 
 
516
.What happens when install tests are run?
 
517
----
 
518
                 | runtest --tool install
 
519
                 V
 
520
            +----+----+
 
521
            | DejaGnu |
 
522
            +----+----+
 
523
                 |
 
524
                 V
 
525
    +------------+---------------+
 
526
    | (file: config/default.exp) |
 
527
    +------------+---------------+
 
528
                 |
 
529
                 V
 
530
    +------------+------------+
 
531
    | (file: lib/install.exp) |
 
532
    +-------------------------+
 
533
----
 
534
 
 
535
==== unit
 
536
 
 
537
.What happens when unit tests are run?
 
538
----
 
539
               | runtest --tool unit
 
540
               V
 
541
          +----+----+
 
542
          | DejaGnu |
 
543
          +----+----+
 
544
               |
 
545
               V
 
546
    +----------+-----------+
 
547
    |          -           |
 
548
    | (file: lib/unit.exp) |
 
549
    +----------------------+
 
550
----
 
551
 
 
552
=== bashrc
 
553
 
 
554
This is the bash configuration file (bashrc) used for testing:
 
555
 
 
556
[source,bash]
 
557
---------------------------------------------------------------------
 
558
include::bashrc[]
 
559
---------------------------------------------------------------------
 
560
 
 
561
 
 
562
=== inputrc
 
563
 
 
564
This is the readline configuration file (inputrc) used for testing:
 
565
 
 
566
[source,bash]
 
567
---------------------------------------------------------------------
 
568
include::inputrc[]
 
569
---------------------------------------------------------------------
 
570
 
 
571
 
 
572
Index
 
573
=====