1Config::Model::Tester(3U)ser Contributed Perl DocumentatiCoonnfig::Model::Tester(3)
2
3
4

NAME

6       Config::Model::Tester - Test framework for Config::Model
7

VERSION

9       version 4.003
10

SYNOPSIS

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

DESCRIPTION

27       This class provides a way to test configuration models with tests
28       files.  This class was designed to tests several models and run 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) is used for the test cases defined in
40       the "*-test-conf.pl" file. The model to test is inferred from the
41       application name to test.
42
43       This file contains a list of test case (explained below) and expects a
44       set of files used as test data. The layout of these test data files is
45       explained in next section.
46
47   Simple test file layout
48       Each test case is represented by a configuration file (not a directory)
49       in the "*-examples" directory. This configuration file is used by the
50       model to test and is copied as "$confdir/$conf_file_name" using the
51       test data structure explained below.
52
53       In the example below, we have 1 app model to test: "lcdproc" and 2
54       tests cases. The app name matches the file specified in
55       "lib/Config/Model/*.d" directory. In this case, the app name matches
56       "lib/Config/Model/system.d/lcdproc"
57
58        t
59        |-- model_test.t
60        \-- model_tests.d           # do not change directory name
61            |-- lcdproc-test-conf.pl   # subtest specification for lcdproc app
62            \-- lcdproc-examples
63                |-- t0              # test case t0
64                \-- LCDD-0.5.5      # test case for older LCDproc
65
66       Subtest specification is written in "lcdproc-test-conf.pl" file (i.e.
67       this module looks for files named like "<app-name>-test-conf.pl>").
68
69       Subtests data is provided in files in directory "lcdproc-examples" (
70       i.e. this modules looks for test data in directory
71       "<model-name>-examples>". "lcdproc-test-conf.pl" contains instructions
72       so that each file is used as a "/etc/LCDd.conf" file during each test
73       case.
74
75       "lcdproc-test-conf.pl" can contain specifications for more test cases.
76       Each test case requires a new file in "lcdproc-examples" directory.
77
78       See "Examples" for a link to the actual LCDproc model tests
79
80   Test file layout for multi-file configuration
81       When a configuration is spread over several files, each test case is
82       provided in a sub-directory. This sub-directory is copied in "conf_dir"
83       (a test parameter as explained below)
84
85       In the example below, the test specification is written in
86       "dpkg-test-conf.pl". Dpkg layout requires several files per test case.
87       "dpkg-test-conf.pl" contains instructions so that each directory under
88       "dpkg-examples" is used.
89
90        t/model_tests.d
91        \-- dpkg-test-conf.pl         # subtest specification
92        \-- dpkg-examples
93            \-- libversion            # example subdir, used as test case name
94                \-- debian            # directory for used by test case
95                    |-- changelog
96                    |-- compat
97                    |-- control
98                    |-- copyright
99                    |-- rules
100                    |-- source
101                    |   \-- format
102                    \-- watch
103
104       See "Examples" for a link to the (many) Dpkg model tests
105
106   More complex file layout
107       Each test case is a sub-directory on the "*-examples" directory and
108       contains several files. The destination of the test files may depend on
109       the system (e.g. the OS). For instance, system wide "ssh_config" is
110       stored in "/etc/ssh" on Linux, and directly in "/etc" on MacOS.
111
112       These files are copied in a test directory using a "setup" parameter in
113       test case specification:
114
115         setup => {
116           test_file_in_example_dir => 'destination'
117         }
118
119       Let's consider this example of 2 tests cases for ssh:
120
121        t/model_tests.d/
122        |-- ssh-test-conf.pl
123        |-- ssh-examples
124            \-- basic
125                |-- system_ssh_config
126                \-- user_ssh_config
127
128       Unfortunately, "user_ssh_config" is a user file, so you need to specify
129       where is located the home directory of the test with another global
130       parameter:
131
132         home_for_test => '/home/joe' ;
133
134       For Linux only, the "setup" parameter is:
135
136        setup => {
137          system_ssh_config => '/etc/ssh/ssh_config',
138          user_ssh_config   => "~/.ssh/config"
139        }
140
141       On the other hand, system wide config file is different on MacOS and
142       the test file must be copied in the correct location. When the value of
143       the "setup" hash is another hash, the key of this other hash is used as
144       to specify the target location for other OS (as returned by Perl $^O
145       variable:
146
147             setup => {
148               'system_ssh_config' => {
149                   'darwin' => '/etc/ssh_config',
150                   'default' => '/etc/ssh/ssh_config',
151               },
152               'user_ssh_config' => "~/.ssh/config"
153             }
154
155       See the actual Ssh and Sshd model tests
156       <https://github.com/dod38fr/config-model-
157       openssh/tree/master/t/model_tests.d>
158
159   Basic test specification
160       Each model subtest is specified in "<app>-test-conf.pl". This file must
161       return a data structure containing the test specifications. Each test
162       data structure contains global parameters (Applied to all tests cases)
163       and test cases parameters (parameters are applied to the test case)
164
165        use strict;
166        use warnings;
167        {
168          # global parameters
169
170          # config file name (used to copy test case into test wr_root/model_tests directory)
171          conf_file_name => "fstab",
172          # config dir where to copy the file (optional)
173          conf_dir => "etc",
174          # home directory for this test
175          home_for_test => '/home/joe'
176
177          tests =>  [
178            {
179              # test case 1
180              name => 'my_first_test',
181              # other test case parameters
182            },
183            {
184              # test case 2
185              name => 'my_second_test',
186              # other test case parameters
187            },
188            # ...
189          ],
190        };
191
192        # do not add 1; at the end of the file
193
194       In the example below, "t0" file is copied in
195       "wr_root/model_tests/test-t0/etc/fstab".
196
197        use strict;
198        use warnings;
199        {
200          # list of tests.
201          tests => [
202            {
203              # test name
204              name => 't0',
205              # add optional specification here for t0 test
206            },
207            {
208              name => 't1',
209              # add optional specification here for t1 test
210            },
211          ]
212        };
213
214       You can suppress warnings by specifying "no_warnings => 1" in each test
215       case. On the other hand, you may also want to check for warnings
216       specified to your model. In this case, you should avoid specifying
217       "no_warnings" here and specify warning tests or warning filters as
218       mentioned below.
219
220       See actual fstab test <https://github.com/dod38fr/config-
221       model/blob/master/t/model_tests.d/fstab-test-conf.pl>.
222
223   Skip a test
224       A test file can be skipped using "skip" global test parameter.
225
226       In this example, test is skipped when not running on a Debian system:
227
228        eval { require AptPkg::Config; };
229        my $skip = ( $@ or not -r '/etc/debian_version' ) ? 1 : 0;
230
231        {
232          skip => $skip,
233          tests => [ ] ,
234        };
235
236   Internal tests or backend tests
237       Some tests require the creation of a configuration class dedicated for
238       test (typically to test corner cases on a backend).
239
240       This test class can be created directly in the test specification by
241       specifying tests classes in "config_classes" global test parameter in
242       an array ref. Each array element is a data structure that use
243       create_config_class parameters.  See for instance the layer test
244       <https://github.com/dod38fr/config-
245       model/blob/master/t/model_tests.d/layer-test-conf.pl> or the test for
246       shellvar backend <https://github.com/dod38fr/config-
247       model/blob/master/t/model_tests.d/backend-shellvar-test-conf.pl>.
248
249       In this case, no application exist for such classes so the model to
250       test must be specified in a global test parameter:
251
252         return {
253           config_classes => [ { name => "Foo", element => ... } , ... ],
254           model_to_test => "Foo",
255           tests => [ ... ]
256         };
257
258   Test specification with arbitrary file names
259       In some models, like "Multistrap", the config file is chosen by the
260       user. In this case, the file name must be specified for each tests
261       case:
262
263        {
264          tests => [ {
265              name        => 'arm',
266              config_file => '/home/foo/my_arm.conf',
267              check       => {},
268           }]
269        };
270
271       See the actual multistrap test <https://github.com/dod38fr/config-
272       model/blob/master/t/model_tests.d/multistrap-test-conf.pl>.
273
274   Backend argument
275       Some application like systemd requires a backend argument specified by
276       user (e.g. a service name for systemd). The parameter "backend_arg" can
277       be specified to emulate this behavior.
278
279   Re-use test data
280       When the input data for test is quite complex (several files), it may
281       be interesting to re-use these data for other test cases. Knowing that
282       test names must be unique, you can re-use test data with "data_from"
283       parameter. For instance:
284
285         tests => [
286           {
287               name  => 'some-test',
288               # ...
289           },
290           {
291               name  => 'some-other-test',
292               data_from  => 'some-test',    # re-use data from test above
293               # ...
294           },
295         ]
296
297       See plainfile backend test <https://github.com/dod38fr/config-
298       model/blob/master/t/model_tests.d/backend-plainfile-test-conf.pl> for a
299       real life example.
300
301   Test scenario
302       Each subtest follow a sequence explained below. Each step of this
303       sequence may be altered by adding test case parameters in
304       "<model-to-test>-test-conf.pl":
305
306       ·   Setup test in "wr_root/model_tests/<subtest name>/". If your
307           configuration file layout depend on the target system, you will
308           have to specify the path using "setup" parameter.  See "Test file
309           layout depending on system".
310
311       ·   Create configuration instance, load config data and check its
312           validity. Use "load_check => 'no'" if your file is not valid.
313
314       ·   Check for config data warnings. You should pass the list of
315           expected warnings that are emitted through Log::Log4Perl. The array
316           ref is passed as is to the "expect" function of "expect" in
317           Test::Log::Lo4Perl. E.g:
318
319               log4perl_load_warnings => [
320                    [ 'Tree.Node', (warn => qr/deprecated/) x 2 ]  ,
321                    [ 'Tree.Element.Value' , ( warn => qr/skipping/) x 2 ]
322               ]
323
324           The Log classes are specified in "cme/Logging".
325
326           Log levels below "warn" are ignored.
327
328           Config::Model is currently transitioning from traditional "warn" to
329           warn logs. To avoid breaking all tests based on this module, the
330           warnings are emitted through Log::Log4Perl only when
331           c<$::_use_log4perl_to_warn> is set. This hack will be removed once
332           all warnings checks in tests are ported to log4perl checks.
333
334       ·   DEPRECATED. Check for config data warning. You should pass the list
335           of expected warnings.  E.g.
336
337               load_warnings => [ qr/Missing/, (qr/deprecated/) x 3 , ],
338
339           Use an empty array_ref to mask load warnings.
340
341       ·   Optionally run update command:
342
343               update => {
344                    [ returns => 'foo' , ]
345                    no_warnings => [ 0 | 1 ], # default 0
346                    quiet => [ 0 | 1], # default 0, passed to update method
347                    loag4perl_update_warnings => [ ... ] # Test::Log::Log4Perl::expect arguments
348            }
349
350           Where:
351
352           ·   "returns" is the expected return value (optional).
353
354           ·   "no_warnings" to suppress the warnings coming from
355               Config::Model::Value. Note that "no_warnings => 1" may be
356               useful for less verbose test.
357
358           ·   "quiet" to suppress progress messages during update.
359
360           ·   "log4perl_update_warnings" is used to check the warnings
361               produced during update. The argument is passed to "expect"
362               function of Test::Log::Log4Perl. See "load_warnings" parameter
363               above for more details.
364
365           ·   DEPRECATED. "update_warnings" is an array ref of quoted regexp
366               (See qr operator) to check the warnings produced during update.
367               use "update => []" to check that no warnings are issued during
368               update.
369
370           All other arguments are passed to "update" method.
371
372       ·   Optionally load configuration data. You should design this config
373           data to suppress any error or warning mentioned above. E.g:
374
375               load => 'binary:seaview Synopsis="multiplatform interface for sequence alignment"',
376
377           See Config::Model::Loader for the syntax of the string accepted by
378           "load" parameter.
379
380       ·   Optionally, run a check before running apply_fix (if any). This
381           step is useful to check warning messages:
382
383              check_before_fix => {
384                 dump_errors   => [ ... ] # optional, see below
385                 load4perl_dump_warnings => [ ... ] # optional, see below
386              }
387
388           Use "dump_errors" if you expect issues:
389
390             check_before_fix => {
391               dump_errors =>  [
392                   # the issues  and a way to fix the issue using Config::Model::Node::load
393                   qr/mandatory/ => 'Files:"*" Copyright:0="(c) foobar"',
394                   qr/mandatory/ => ' License:FOO text="foo bar" ! Files:"*" License short_name="FOO" '
395               ],
396             }
397
398           Likewise, specify any expected warnings:
399
400             check_before_fix => {
401                   log4perl_dump_warnings => [ ... ],
402             }
403
404           "log4perl_dump_warnings" passes the array ref content to "expect"
405           function of Test::Log::Log4Perl.
406
407           Both "log4perl_dump_warnings" and "dump_errors" can be specified in
408           "check_before_fix" hash.
409
410       ·   Optionally, call apply_fixes:
411
412               apply_fix => 1,
413
414       ·   Call dump_tree to check the validity of the data after optional
415           "apply_fix". This step is not optional.
416
417           As with "check_before_fix", both "dump_errors" or "dump_warnings"
418           can be used.
419
420       ·   Run specific content check to verify that configuration data was
421           retrieved correctly:
422
423               check => {
424                   'fs:/proc fs_spec' => "proc",
425                   'fs:/proc fs_file' => "/proc",
426                   'fs:/home fs_file' => "/home",
427               },
428
429           The keys of the hash points to the value to be checked using the
430           syntax described in "grab" in Config::Model::Role::Grab.
431
432           Multiple check on the same item can be applied with a array ref:
433
434               check => [
435                   Synopsis => 'fix undefined path_max for st_size zero',
436                   Description => [ qr/^The downstream/,  qr/yada yada/ ]
437               ]
438
439           You can run check using different check modes (See "fetch" in
440           Config::Model::Value) by passing a hash ref instead of a scalar :
441
442               check  => {
443                   'sections:debian packages:0' => { mode => 'layered', value => 'dpkg-dev' },
444                   'sections:base packages:0'   => { mode => 'layered', value => "gcc-4.2-base' },
445               },
446
447           The whole hash content (except "value") is passed to  grab and
448           fetch
449
450           A regexp can also be used to check value:
451
452              check => {
453                 "License text" => qr/gnu/i,
454              }
455
456           And specification can nest hash or array style:
457
458              check => {
459                 "License:0 text" => qr/gnu/i,
460                 "License:1 text" => [ qr/gnu/i, qr/Stallman/ ],
461                 "License:2 text" => { mode => 'custom', value => [ qr/gnu/i , qr/Stallman/ ] },
462                 "License:3 text" => [ qr/General/], { mode => 'custom', value => [ qr/gnu/i , qr/Stallman/ ] },
463              }
464
465       ·   Verify if a hash contains one or more keys (or keys matching a
466           regexp):
467
468            has_key => [
469               'sections' => 'debian', # sections must point to a hash element
470               'control' => [qw/source binary/],
471               'copyright Files' => qr/.c$/,
472               'copyright Files' => [qr/\.h$/], qr/\.c$/],
473            ],
474
475       ·   Verify that a hash does not have a key (or a key matching a
476           regexp):
477
478            has_not_key => [
479               'copyright Files' => qr/.virus$/ # silly, isn't ?
480            ],
481
482       ·   Verify annotation extracted from the configuration file comments:
483
484               verify_annotation => {
485                       'source Build-Depends' => "do NOT add libgtk2-perl to build-deps (see bug #554704)",
486                       'source Maintainer' => "what a fine\nteam this one is",
487                   },
488
489       ·   Write back the config data in "wr_root/model_tests/<subtest
490           name>/".  Note that write back is forced, so the tested
491           configuration files are written back even if the configuration
492           values were not changed during the test.
493
494           You can skip warning when writing back with the global :
495
496               no_warnings => 1,
497
498       ·   Check the content of the written files(s) with
499           Test::File::Contents. Tests can be grouped in an array ref:
500
501              file_contents => {
502                       "/home/foo/my_arm.conf" => "really big string" ,
503                       "/home/bar/my_arm.conf" => [ "really big string" , "another"], ,
504                   }
505
506              file_contents_like => {
507                       "/home/foo/my_arm.conf" => [ qr/should be there/, qr/as well/ ] ,
508              }
509
510              file_contents_unlike => {
511                       "/home/foo/my_arm.conf" => qr/should NOT be there/ ,
512              }
513
514       ·   Check the mode of the written files:
515
516             file_mode => {
517                "~/.ssh/ssh_config"     => oct(600), # better than 0600
518                "debian/stuff.postinst" => oct(755),
519             }
520
521           Only the last four octets of the mode are tested. I.e. the test is
522           done with " $file_mode & oct(7777) "
523
524           Note: this test is skipped on Windows
525
526       ·   Check added or removed configuration files. If you expect changes,
527           specify a subref to alter the file list:
528
529               file_check_sub => sub {
530                   my $list_ref = shift ;
531                   # file added during tests
532                   push @$list_ref, "/debian/source/format" ;
533               },
534
535           Note that actual and expected file lists are sorted before check,
536           adding a file can be done with "push".
537
538       ·   Copy all config data from "wr_root/model_tests/<subtest name>/" to
539           "wr_root/model_tests/<subtest name>-w/". This steps is necessary to
540           check that configuration written back has the same content as the
541           original configuration.
542
543       ·   Create a second configuration instance to read the conf file that
544           was just copied (configuration data is checked.)
545
546       ·   You can skip the load check if the written file still contain
547           errors (e.g.  some errors were ignored and cannot be fixed) with
548           "load_check2 => 'no'"
549
550       ·   Optionally load configuration data in the second instance. You
551           should design this config data to suppress any error or warning
552           that occur in the step below. E.g:
553
554               load2 => 'binary:seaview',
555
556           See Config::Model::Loader for the syntax of the string accepted by
557           "load2" parameter.
558
559       ·   Compare data read from original data.
560
561       ·   Run specific content check on the written config file to verify
562           that configuration data was written and retrieved correctly:
563
564               wr_check => {
565                   'fs:/proc fs_spec' =>          "proc" ,
566                   'fs:/proc fs_file' =>          "/proc",
567                   'fs:/home fs_file' =>          "/home",
568               },
569
570           Like the "check" item explained above, you can run "wr_check" using
571           different check modes.
572
573   Running the test
574       Run all tests with one of these commands:
575
576        prove -l t/model_test.t :: [ --trace ] [ --log ] [ --error ] [ <model_name> [ <regexp> ]]
577        perl -Ilib t/model_test.t  [ --trace ] [ --log ] [ --error ] [ <model_name> [ <regexp> ]]
578
579       By default, all tests are run on all models.
580
581       You can pass arguments to "t/model_test.t":
582
583       ·   Optional parameters: "--trace" to get test traces. "--error" to get
584           stack trace in case of errors, "--log" to have logs. E.g.
585
586             # run with log and error traces
587             prove -lv t/model_test.t :: --error --logl
588
589       ·   The model name to tests. E.g.:
590
591             # run only fstab tests
592             prove -lv t/model_test.t :: fstab
593
594       ·   A regexp to filter subtest E.g.:
595
596             # run only fstab tests foobar subtest
597             prove -lv t/model_test.t :: fstab foobar
598
599             # run only fstab tests foo subtest
600             prove -lv t/model_test.t :: fstab '^foo$'
601

Examples

603       Some of these examples may still use global variables (which is
604       deprecated). Such files may be considered as buggy after Aug 2019.
605       Please warn the author if you find one.
606
607       ·   LCDproc <http://lcdproc.org> has a single configuration file:
608           "/etc/LCDd.conf". Here's LCDproc test layout
609           <https://github.com/dod38fr/config-model-
610           lcdproc/tree/master/t/model_tests.d> and the test specification
611           <https://github.com/dod38fr/config-model-
612           lcdproc/blob/master/t/model_tests.d/lcdd-test-conf.pl>
613
614       ·   Dpkg packages are constructed from several files. These files are
615           handled like configuration files by Config::Model::Dpkg. The test
616           layout <http://anonscm.debian.org/gitweb/?p=pkg-
617           perl/packages/libconfig-model-dpkg-
618           perl.git;a=tree;f=t/model_tests.d;hb=HEAD> features test with
619           multiple file in dpkg-examples
620           <http://anonscm.debian.org/gitweb/?p=pkg-perl/packages/libconfig-
621           model-dpkg-perl.git;a=tree;f=t/model_tests.d/dpkg-
622           examples;hb=HEAD>.  The test is specified in dpkg-test-conf.pl
623           <http://anonscm.debian.org/gitweb/?p=pkg-perl/packages/libconfig-
624           model-dpkg-perl.git;a=blob_plain;f=t/model_tests.d/dpkg-test-
625           conf.pl;hb=HEAD>
626
627       ·   multistrap-test-conf.pl <https://github.com/dod38fr/config-
628           model/blob/master/t/model_tests.d/multistrap-test-conf.pl> and
629           multistrap-examples <https://github.com/dod38fr/config-
630           model/tree/master/t/model_tests.d/multistrap-examples> specify a
631           test where the configuration file name is not imposed by the
632           application. The file name must then be set in the test
633           specification.
634
635       ·   backend-shellvar-test-conf.pl <https://github.com/dod38fr/config-
636           model/blob/master/t/model_tests.d/backend-shellvar-test-conf.pl> is
637           a more complex example showing how to test a backend. The test is
638           done creating a dummy model within the test specification.
639

CREDITS

641       In alphabetical order:
642
643       ·   Cyrille Bollu
644
645       Many thanks for your help.
646

SEE ALSO

648       ·   Config::Model
649
650       ·   Test::More
651

AUTHOR

653       Dominique Dumont
654
656       This software is Copyright (c) 2013-2019 by Dominique Dumont.
657
658       This is free software, licensed under:
659
660         The GNU Lesser General Public License, Version 2.1, February 1999
661

SUPPORT

663   Websites
664       The following websites have more information about this module, and may
665       be of help to you. As always, in addition to those websites please use
666       your favorite search engine to discover more resources.
667
668       ·   Search CPAN
669
670           The default CPAN search engine, useful to view POD in HTML format.
671
672           <http://search.cpan.org/dist/Config-Model-Tester>
673
674       ·   AnnoCPAN
675
676           The AnnoCPAN is a website that allows community annotations of Perl
677           module documentation.
678
679           <http://annocpan.org/dist/Config-Model-Tester>
680
681       ·   CPAN Ratings
682
683           The CPAN Ratings is a website that allows community ratings and
684           reviews of Perl modules.
685
686           <http://cpanratings.perl.org/d/Config-Model-Tester>
687
688       ·   CPANTS
689
690           The CPANTS is a website that analyzes the Kwalitee ( code metrics )
691           of a distribution.
692
693           <http://cpants.cpanauthors.org/dist/Config-Model-Tester>
694
695       ·   CPAN Testers
696
697           The CPAN Testers is a network of smoke testers who run automated
698           tests on uploaded CPAN distributions.
699
700           <http://www.cpantesters.org/distro/C/Config-Model-Tester>
701
702       ·   CPAN Testers Matrix
703
704           The CPAN Testers Matrix is a website that provides a visual
705           overview of the test results for a distribution on various
706           Perls/platforms.
707
708           <http://matrix.cpantesters.org/?dist=Config-Model-Tester>
709
710       ·   CPAN Testers Dependencies
711
712           The CPAN Testers Dependencies is a website that shows a chart of
713           the test results of all dependencies for a distribution.
714
715           <http://deps.cpantesters.org/?module=Config::Model::Tester>
716
717   Bugs / Feature Requests
718       Please report any bugs or feature requests by email to "ddumont at
719       cpan.org", or through the web interface at
720       <https://github.com/dod38fr/config-model-tester/issues>. You will be
721       automatically notified of any progress on the request by the system.
722
723   Source Code
724       The code is open to the world, and available for you to hack on. Please
725       feel free to browse it and play with it, or whatever. If you want to
726       contribute patches, please send me a diff or prod me to pull from your
727       repository :)
728
729       <http://github.com/dod38fr/config-model-tester.git>
730
731         git clone git://github.com/dod38fr/config-model-tester.git
732
733
734
735perl v5.30.0                      2019-07-26          Config::Model::Tester(3)
Impressum