1Config::Model::Tester(3U)ser Contributed Perl DocumentatiCoonnfig::Model::Tester(3)
2
3
4
6 Config::Model::Tester - Test framework for Config::Model
7
9 version 3.006
10
12 In your test file (typically "t/model_test.t"):
13
14 use warnings;
15 use strict;
16
17 use Config::Model::Tester ;
18 use ExtUtils::testlib;
19
20 run_tests() ;
21
22 Run tests with:
23
24 perl t/model_test.t [ --log ] [--error] [--trace] [ subtest [ test_case ] ]
25
27 This class provides a way to test configuration models with tests
28 files. This class was designed to tests several models and several
29 tests cases per model.
30
31 A specific layout for test files must be followed.
32
33 Sub test specification
34 Each subtest is defined in a file like:
35
36 t/model_tests.d/<app-name>-test-conf.pl
37
38 This file specifies that "app-name" (which is defined in
39 "lib/Config/Model/*.d" directory) will be used for the test cases
40 defined in the "*-test-conf.pl" file.
41
42 This file contains a list of test case (explained below) and expects a
43 set of files used as test data. The layout of these test data files is
44 explained in next section.
45
46 Simple test file layout
47 Each test case is represented by a configuration file (not a directory)
48 in the "*-examples" directory. This configuration file will be used by
49 the model to test and is copied as "$confdir/$conf_file_name" using the
50 global variables explained below.
51
52 In the example below, we have 1 app model to test: "lcdproc" and 2
53 tests cases. The app name matches the file specified in
54 "lib/Config/Model/*.d" directory. In this case, the app name matches
55 "lib/Config/Model/system.d/lcdproc"
56
57 t
58 |-- model_test.t
59 \-- model_tests.d # do not change directory name
60 |-- lcdproc-test-conf.pl # subtest specification for lcdproc app
61 \-- lcdproc-examples
62 |-- t0 # test case t0
63 \-- LCDD-0.5.5 # test case for older LCDproc
64
65 Subtest specification is written in "lcdproc-test-conf.pl" file (i.e.
66 this modules looks for files named like "<app-name>-test-conf.pl>").
67
68 Subtests data is provided in files in directory "lcdproc-examples" (
69 i.e. this modules looks for test data in directory
70 "<model-name>-examples>". "lcdproc-test-conf.pl" contains instructions
71 so that each file will be used as a "/etc/LCDd.conf" file during each
72 test case.
73
74 "lcdproc-test-conf.pl" can contain specifications for more test cases.
75 Each test case requires a new file in "lcdproc-examples" directory.
76
77 See "Examples" for a link to the actual LCDproc model tests
78
79 Test file layout for multi-file configuration
80 When a configuration is spread over several files, each test case is
81 provided in a sub-directory. This sub-directory is copied in $conf_dir
82 (a global variable as explained below)
83
84 In the example below, the test specification is written in
85 "dpkg-test-conf.pl". Dpkg layout requires several files per test case.
86 "dpkg-test-conf.pl" will contain instructions so that each directory
87 under "dpkg-examples" will be used.
88
89 t/model_tests.d
90 \-- dpkg-test-conf.pl # subtest specification
91 \-- dpkg-examples
92 \-- libversion # example subdir, used as test case name
93 \-- debian # directory for used by test case
94 |-- changelog
95 |-- compat
96 |-- control
97 |-- copyright
98 |-- rules
99 |-- source
100 | \-- format
101 \-- watch
102
103 See "Examples" for a link to the (many) Dpkg model tests
104
105 More complex file layout
106 Each test case is a sub-directory on the "*-examples" directory and
107 contains several files. The destination of the test files may depend on
108 the system (e.g. the OS). For instance, system wide "ssh_config" is
109 stored in "/etc/ssh" on Linux, and directly in "/etc" on MacOS.
110
111 These files are copied in a test directory using a "setup" parameter:
112
113 setup => {
114 test_file_in_example_dir => 'destination'
115 }
116
117 Let's consider this example of 2 tests cases for ssh:
118
119 t/model_tests.d/
120 |-- ssh-test-conf.pl
121 |-- ssh-examples
122 \-- basic
123 |-- system_ssh_config
124 \-- user_ssh_config
125
126 Unfortunately, "user_ssh_config" is a user file, so you specify where
127 the home directory for the tests with another global variable:
128
129 $home_for_test = '/home/joe' ;
130
131 For Linux only, the "setup" parameter is:
132
133 setup => {
134 'system_ssh_config' => '/etc/ssh/ssh_config',
135 'user_ssh_config' => "~/.ssh/config"
136 }
137
138 On the other hand, system wide config file is different on MacOS and
139 the test file must be copied in the correct location. When the value of
140 the "setup" hash is another hash, the key of this other hash is used as
141 to specify the target location for other OS (as returned by Perl $^O
142 variable:
143
144 setup => {
145 'system_ssh_config' => {
146 'darwin' => '/etc/ssh_config',
147 'default' => '/etc/ssh/ssh_config',
148 },
149 'user_ssh_config' => "~/.ssh/config"
150 }
151
152 See the actual Ssh and Sshd model tests
153 <https://github.com/dod38fr/config-model-
154 openssh/tree/master/t/model_tests.d>
155
156 Basic test specification
157 Each model subtest is specified in "<model>-test-conf.pl". This file
158 contains a set of global variables. (yes, global variables are often
159 bad ideas in programs, but they are handy for tests):
160
161 # config file name (used to copy test case into test wr_root/model_tests directory)
162 $conf_file_name = "fstab" ;
163 # config dir where to copy the file (optional)
164 #$conf_dir = "etc" ;
165 # home directory for this test
166 $home_for_test = '/home/joe' ;
167
168 Here, "t0" file will be copied in
169 "wr_root/model_tests/test-t0/etc/fstab".
170
171 # config model name to test
172 $model_to_test = "Fstab" ;
173
174 # list of tests. This modules looks for @tests global variable
175 @tests = (
176 {
177 # test name
178 name => 't0',
179 # add optional specification here for t0 test
180 },
181 {
182 name => 't1',
183 # add optional specification here for t1 test
184 },
185 );
186
187 1; # to keep Perl happy
188
189 You can suppress warnings by specifying "no_warnings => 1". On the
190 other hand, you may also want to check for warnings specified to your
191 model. In this case, you should avoid specifying "no_warnings" here and
192 specify warning tests or warning filters as mentioned below.
193
194 See actual fstab test <https://github.com/dod38fr/config-
195 model/blob/master/t/model_tests.d/fstab-test-conf.pl>.
196
197 Skip a test
198 A test file can be skipped using $skip global variable.
199
200 In this example, test is skipped when not running on a Debian system:
201
202 eval { require AptPkg::Config; };
203 $skip = ( $@ or not -r '/etc/debian_version' ) ? 1 : 0;
204
205 Internal tests or backend tests
206 Some tests will require the creation of a configuration class dedicated
207 for test (typically to test corner cases on a backend).
208
209 This test class can be created directly in the test specification by
210 calling create_config_class on $model variable. See for instance the
211 layer test <https://github.com/dod38fr/config-
212 model/blob/master/t/model_tests.d/layer-test-conf.pl> or the test for
213 shellvar backend <https://github.com/dod38fr/config-
214 model/blob/master/t/model_tests.d/backend-shellvar-test-conf.pl>.
215
216 Test specification with arbitrary file names
217 In some models like "Multistrap", the config file is chosen by the
218 user. In this case, the file name must be specified for each tests
219 case:
220
221 # not needed if test file is named multistrap-test-conf.pl
222 $model_to_test = "Multistrap";
223
224 @tests = (
225 {
226 name => 'arm',
227 config_file => '/home/foo/my_arm.conf',
228 check => {},
229 },
230 );
231
232 See the actual multistrap test <https://github.com/dod38fr/config-
233 model/blob/master/t/model_tests.d/multistrap-test-conf.pl>.
234
235 Backend argument
236 Some application like systemd requires a backend argument specified by
237 User (e.g. a service name for systemd). The parameter "backend_arg" can
238 be specified to emulate this behavior.
239
240 Re-use test data
241 When the input data for test is quite complex (several files), it may
242 be interested to re-use these data for other tests case. Knowing that
243 test name must must unique, you can re-use test data with "data_from"
244 parameter. For instance:
245
246 @tests = (
247 {
248 name => 'some-test',
249 # ...
250 },
251 {
252 name => 'some-other-test',
253 data_from => 'some-test', # re-use data from test above
254 # ...
255 },
256
257 See plainfile backend test <https://github.com/dod38fr/config-
258 model/blob/master/t/model_tests.d/backend-plainfile-test-conf.pl> for a
259 real life example.
260
261 Test scenario
262 Each subtest follow a sequence explained below. Each step of this
263 sequence may be altered by adding specification in
264 "<model-to-test>-test-conf.pl":
265
266 · Setup test in "wr_root/model_tests/<subtest name>/". If your
267 configuration file layout depend on the target system, you will
268 have to specify the path using "setup" parameter. See "Test file
269 layout depending on system".
270
271 · Create configuration instance, load config data and check its
272 validity. Use "load_check => 'no'" if your file is not valid.
273
274 · Check for config data warnings. You should pass the list of
275 expected warnings that are emitted through Log::Log4Perl. The array
276 ref is passed as is to the "expect" function of "expect" in
277 Test::Log::Lo4Perl. E.g:
278
279 log4perl_load_warnings => [
280 [ 'Tree.Node', (warn => qr/deprecated/) x 2 ] ,
281 [ 'Tree.Element.Value' , ( warn => qr/skipping/) x 2 ]
282 ]
283
284 The Log classes are specified in "cme/Logging".
285
286 Log levels below "warn" are ignored.
287
288 Config::Model is currently transitioning from traditional "warn" to
289 warn logs. To avoid breaking all tests based on this module, the
290 warnings are emitted through Log::Log4Perl only when
291 c<$::_use_log4perl_to_warn> is set. This hack will be removed once
292 all warnings checks in tests are ported to log4perl checks.
293
294 · DEPRECATED. Check for config data warning. You should pass the list
295 of expected warnings. E.g.
296
297 load_warnings => [ qr/Missing/, (qr/deprecated/) x 3 , ],
298
299 Use an empty array_ref to mask load warnings.
300
301 · Optionally run update command:
302
303 update => {
304 [ returns => 'foo' , ]
305 no_warnings => [ 0 | 1 ], # default 0
306 quiet => [ 0 | 1], # default 0, passed to update method
307 loag4perl_update_warnings => [ ... ] # Test::Log::Log4Perl::expect arguments
308 }
309
310 Where:
311
312 · "returns" is the expected return value (optional).
313
314 · "no_warnings" to suppress the warnings coming from
315 Config::Model::Value. Note that "no_warnings => 1" may be
316 useful for less verbose test.
317
318 · "quiet" to suppress progress messages during update.
319
320 · "log4perl_update_warnings" is used to check the warnings
321 produced
322 during update. The argument is passed to "expect" function of
323 Test::Log::Log4Perl. See "load_warnings" parameter above for
324 more
325 details.
326
327 · DEPRECATED. "update_warnings" is an array ref of quoted regexp
328 (See qr operator) to check the warnings produced during update.
329 use "update => []" to check that no warnings are issued during
330 update.
331
332 All other arguments are passed to "update" method.
333
334 · Optionally load configuration data. You should design this config
335 data to suppress any error or warning mentioned above. E.g:
336
337 load => 'binary:seaview Synopsis="multiplatform interface for sequence alignment"',
338
339 See Config::Model::Loader for the syntax of the string accepted by
340 "load" parameter.
341
342 · Optionally, run a check before running apply_fix (if any). This
343 step is useful to check warning messages:
344
345 check_before_fix => {
346 dump_errors => [ ... ] # optional, see below
347 load4perl_dump_warnings => [ ... ] # optional, see below
348 }
349
350 Use "dump_errors" if you expect issues:
351
352 check_before_fix => {
353 dump_errors => [
354 # the issues and a way to fix the issue using Config::Model::Node::load
355 qr/mandatory/ => 'Files:"*" Copyright:0="(c) foobar"',
356 qr/mandatory/ => ' License:FOO text="foo bar" ! Files:"*" License short_name="FOO" '
357 ],
358 }
359
360 Likewise, specify any expected warnings:
361
362 check_before_fix => {
363 log4perl_dump_warnings => [ ... ],
364 }
365
366 "log4perl_dump_warnings" passes the array ref content to "expect"
367 function of Test::Log::Log4Perl.
368
369 Both "log4perl_dump_warnings" and "dump_errors" can be specified in
370 "check_before_fix" hash.
371
372 · Optionally, call apply_fixes:
373
374 apply_fix => 1,
375
376 · Call dump_tree to check the validity of the data after optional
377 "apply_fix". This step is not optional.
378
379 As with "check_before_fix", both "dump_errors" or "dump_warnings"
380 can be used.
381
382 · Run specific content check to verify that configuration data was
383 retrieved correctly:
384
385 check => {
386 'fs:/proc fs_spec', "proc" ,
387 'fs:/proc fs_file', "/proc" ,
388 'fs:/home fs_file', "/home",
389 },
390
391 The keys of the hash points to the value to be checked using the
392 syntax described in "grab(...)" in Config::Model::AnyThing:.
393
394 You can run check using different check modes (See "fetch( ... )"
395 in Config::Model::Value) by passing a hash ref instead of a scalar
396 :
397
398 check => {
399 'sections:debian packages:0' , { mode => 'layered', value => 'dpkg-dev' },
400 'sections:base packages:0', { mode => 'layered', value => "gcc-4.2-base' },
401 },
402
403 The whole hash content (except "value") is passed to grab and
404 fetch
405
406 A regexp can also be used to check value:
407
408 check => {
409 "License text" => qr/gnu/i,
410 "License text" => { mode => 'custom', value => qr/gnu/i },
411 }
412
413 · Verify if a hash contains one or more keys (or keys matching a
414 regexp):
415
416 has_key => [
417 'sections' => 'debian', # sections must point to a hash element
418 'control' => [qw/source binary/],
419 'copyright Files' => qr/.c$/,
420 'copyright Files' => [qr/\.h$/], qr/\.c$/],
421 ],
422
423 · Verify that a hash has not a key (or a key matching a regexp):
424
425 has_not_key => [
426 'copyright Files' => qr/.virus$/ # silly, isn't ?
427 ],
428
429 · Verify annotation extracted from the configuration file comments:
430
431 verify_annotation => {
432 'source Build-Depends' => "do NOT add libgtk2-perl to build-deps (see bug #554704)",
433 'source Maintainer' => "what a fine\nteam this one is",
434 },
435
436 · Write back the config data in "wr_root/model_tests/<subtest
437 name>/". Note that write back is forced, so the tested
438 configuration files are written back even if the configuration
439 values were not changed during the test.
440
441 You can skip warning when writing back with the global :
442
443 no_warnings => 1,
444
445 · Check the content of the written files(s) with
446 Test::File::Contents. Tests can be grouped in an array ref:
447
448 file_contents => {
449 "/home/foo/my_arm.conf" => "really big string" ,
450 "/home/bar/my_arm.conf" => [ "really big string" , "another"], ,
451 }
452
453 file_contents_like => {
454 "/home/foo/my_arm.conf" => [ qr/should be there/, qr/as well/ ] ,
455 }
456
457 file_contents_unlike => {
458 "/home/foo/my_arm.conf" => qr/should NOT be there/ ,
459 }
460
461 · Check the mode of the written files:
462
463 file_mode => {
464 "~/.ssh/ssh_config" => 0600, # octal mode
465 "debian/stuff.postinst" => 0755,
466 }
467
468 Only the last four octets of the mode are tested. I.e. the test is
469 done with " $file_mode & 07777 "
470
471 Note: this test is skipped on Windows
472
473 · Check added or removed configuration files. If you expect changes,
474 specify a subref to alter the file list:
475
476 file_check_sub => sub {
477 my $list_ref = shift ;
478 # file added during tests
479 push @$list_ref, "/debian/source/format" ;
480 },
481
482 Note that actual and expected file lists are sorted before check,
483 adding a file can be done with "push".
484
485 · Copy all config data from "wr_root/model_tests/<subtest name>/" to
486 "wr_root/model_tests/<subtest name>-w/". This steps is necessary to
487 check that configuration written back has the same content as the
488 original configuration.
489
490 · Create a second configuration instance to read the conf file that
491 was just copied (configuration data is checked.)
492
493 · You can skip the load check if the written file still contain
494 errors (e.g. some errors were ignored and cannot be fixed) with
495 "load_check2 => 'no'"
496
497 · Optionally load configuration data in the second instance. You
498 should design this config data to suppress any error or warning
499 that occur in the step below. E.g:
500
501 load2 => 'binary:seaview',
502
503 See Config::Model::Loader for the syntax of the string accepted by
504 "load2" parameter.
505
506 · Compare data read from original data.
507
508 · Run specific content check on the written config file to verify
509 that configuration data was written and retrieved correctly:
510
511 wr_check => {
512 'fs:/proc fs_spec' => "proc" ,
513 'fs:/proc fs_file' => "/proc",
514 'fs:/home fs_file' => "/home",
515 },
516
517 Like the "check" item explained above, you can run "wr_check" using
518 different check modes.
519
520 Running the test
521 Run all tests with one of these commands:
522
523 prove -l t/model_test.t :: [ t|l|e [ <model_name> [ <regexp> ]]]
524 perl -Ilib t/model_test.t [ t|l|e [ <model_name> [ <regexp> ]]]
525
526 By default, all tests are run on all models.
527
528 You can pass arguments to "t/model_test.t":
529
530 · a bunch of letters. 't' to get test traces. 'e' to get stack trace
531 in case of errors, 'l' to have logs. All other letters are ignored.
532 E.g.
533
534 # run with log and error traces
535 prove -lv t/model_test.t :: el
536
537 · The model name to tests. E.g.:
538
539 # run only fstab tests
540 prove -lv t/model_test.t :: x fstab
541
542 · A regexp to filter subtest E.g.:
543
544 # run only fstab tests foobar subtest
545 prove -lv t/model_test.t :: x fstab foobar
546
547 # run only fstab tests foo subtest
548 prove -lv t/model_test.t :: x fstab '^foo$'
549
551 · LCDproc <http://lcdproc.org> has a single configuration file:
552 "/etc/LCDd.conf". Here's LCDproc test layout
553 <https://github.com/dod38fr/config-model-
554 lcdproc/tree/master/t/model_tests.d> and the test specification
555 <https://github.com/dod38fr/config-model-
556 lcdproc/blob/master/t/model_tests.d/lcdd-test-conf.pl>
557
558 · Dpkg packages are constructed from several files. These files are
559 handled like configuration files by Config::Model::Dpkg. The test
560 layout <http://anonscm.debian.org/gitweb/?p=pkg-
561 perl/packages/libconfig-model-dpkg-
562 perl.git;a=tree;f=t/model_tests.d;hb=HEAD> features test with
563 multiple file in dpkg-examples
564 <http://anonscm.debian.org/gitweb/?p=pkg-perl/packages/libconfig-
565 model-dpkg-perl.git;a=tree;f=t/model_tests.d/dpkg-
566 examples;hb=HEAD>. The test is specified in dpkg-test-conf.pl
567 <http://anonscm.debian.org/gitweb/?p=pkg-perl/packages/libconfig-
568 model-dpkg-perl.git;a=blob_plain;f=t/model_tests.d/dpkg-test-
569 conf.pl;hb=HEAD>
570
571 · multistrap-test-conf.pl <https://github.com/dod38fr/config-
572 model/blob/master/t/model_tests.d/multistrap-test-conf.pl> and
573 multistrap-examples <https://github.com/dod38fr/config-
574 model/tree/master/t/model_tests.d/multistrap-examples> specify a
575 test where the configuration file name is not imposed by the
576 application. The file name must then be set in the test
577 specification.
578
579 · backend-shellvar-test-conf.pl <https://github.com/dod38fr/config-
580 model/blob/master/t/model_tests.d/backend-shellvar-test-conf.pl> is
581 a more complex example showing how to test a backend. The test is
582 done creating a dummy model within the test specification.
583
585 · Config::Model
586
587 · Test::More
588
590 Dominique Dumont
591
593 This software is Copyright (c) 2013-2018 by Dominique Dumont.
594
595 This is free software, licensed under:
596
597 The GNU Lesser General Public License, Version 2.1, February 1999
598
600 Websites
601 The following websites have more information about this module, and may
602 be of help to you. As always, in addition to those websites please use
603 your favorite search engine to discover more resources.
604
605 · Search CPAN
606
607 The default CPAN search engine, useful to view POD in HTML format.
608
609 <http://search.cpan.org/dist/Config-Model-Tester>
610
611 · AnnoCPAN
612
613 The AnnoCPAN is a website that allows community annotations of Perl
614 module documentation.
615
616 <http://annocpan.org/dist/Config-Model-Tester>
617
618 · CPAN Ratings
619
620 The CPAN Ratings is a website that allows community ratings and
621 reviews of Perl modules.
622
623 <http://cpanratings.perl.org/d/Config-Model-Tester>
624
625 · CPANTS
626
627 The CPANTS is a website that analyzes the Kwalitee ( code metrics )
628 of a distribution.
629
630 <http://cpants.cpanauthors.org/dist/Config-Model-Tester>
631
632 · CPAN Testers
633
634 The CPAN Testers is a network of smoke testers who run automated
635 tests on uploaded CPAN distributions.
636
637 <http://www.cpantesters.org/distro/C/Config-Model-Tester>
638
639 · CPAN Testers Matrix
640
641 The CPAN Testers Matrix is a website that provides a visual
642 overview of the test results for a distribution on various
643 Perls/platforms.
644
645 <http://matrix.cpantesters.org/?dist=Config-Model-Tester>
646
647 · CPAN Testers Dependencies
648
649 The CPAN Testers Dependencies is a website that shows a chart of
650 the test results of all dependencies for a distribution.
651
652 <http://deps.cpantesters.org/?module=Config::Model::Tester>
653
654 Bugs / Feature Requests
655 Please report any bugs or feature requests by email to "ddumont at
656 cpan.org", or through the web interface at
657 <https://github.com/dod38fr/config-model-tester/issues>. You will be
658 automatically notified of any progress on the request by the system.
659
660 Source Code
661 The code is open to the world, and available for you to hack on. Please
662 feel free to browse it and play with it, or whatever. If you want to
663 contribute patches, please send me a diff or prod me to pull from your
664 repository :)
665
666 <http://github.com/dod38fr/config-model-tester.git>
667
668 git clone git://github.com/dod38fr/config-model-tester.git
669
670
671
672perl v5.28.0 2018-07-14 Config::Model::Tester(3)