NAME

    XT::Files - standard interface for author tests to find files to check

VERSION

    Version 0.001

SYNOPSIS

    In your distribution, add a XT::Files configuration file (optional):

        [Default]
        dirs = 0

        [Dirs]
        bin = script
        module = lib
        test = t
        test = xt

    In a .t file (optional):

        use XT::Files;

        my $xt = XT::Files->initialize( -config => undef ));
        $xt->bin_dir('bin');
        $xt->module_dir('lib');
        $xt->test_dir('t');

    In a Test module (optional):

        use Test::XTFiles;

        my @files = Test::XTFiles->new->all_perl_files;

DESCRIPTION

    Author tests often iterate over your distributions files to check them.
    Unfortunately, every XT test uses its own code and defaults, to find
    the files to check, which means they often don't fit the need of your
    distribution. Common problems are not checking bin or script or, if
    they do, assuming Perl files in bin or script end in .pl.

    The idea of XT::Files is that it's the Tests that know what they want
    to check (e.g. module files), but it's the distribution that knows
    where these files can be found (e.g. in the lib directory and in the
    t/lib directory).

    Without XT::Files you are probably adding the same code to multiple .t
    files under xt that iterate over a check function of the test.

    XT::Files is a standard interface that makes it easy for author tests
    to ask the distribution for the kind of files it would like to test.
    And it can easily be used for author tests that don't support XT::Files
    to have the same set of files tested with every test.

    Note: This is for author tests only. Your own distributions tests
    already know which files to test.

USAGE

 Usage for distribution authors

    The distribution can (and should) use an XT::Files configuration file.
    The default names for the file is either .xtfilesrc or xtfiles.ini in
    the root directory of your distribution. Only one of these files must
    exist. If you put it in a different location or name it differently,
    you have to load it in every .t file

        XT::Files->initialize( -config => 'maint/xt_files.txt' );

    The config file contain a global section and a section for every used
    plugin. Comments start with either # or ;.

    The same plugin can be run multiple times by adding multiple sections
    with the same name. Sections of the same name are not merged.

        # require at least this version of XT::Files
        :version = 0.001

        # XT::Files::Plugin::Default
        # the default configuration plugin
        [Default]
        # add the default directories (this is the default)
        dirs = 1
        # add the default excludes (this is the default)
        excludes = 1

        # XT::Files::Plugin::Dirs
        # add directories with the bin_dir, module_dir or test_dir method
        # from XT::Files
        [Dirs]
        bin = maint
        module = maint/lib
        test = maint/t

        # XT::Files::Plugin::Files
        # add files with the bin_file, module_file or test_file method
        # from XT::Files
        [Files]
        bin = maint/config.pl
        pod = maint/contribute.pod
        module = maint/config.pm

        # XT::Files::Plugin::Excludes
        # add exclude patterns
        [Excludes]
        exclude = [.]old$

        # add a directory to @INC to load plugins contained in the distribution
        [lib]
        lib = maint/plugin

        # load a plugin from outside of the XT::Files::Plugin namesapce
        # this is most likely used to load a plugin contained in the distribution
        [=Local::MyPlugin]

    The configuration is used to tell tests which files are what. A file
    can be of the following types.

      * bin

      These are executable Perl files. For most distributions they live in
      bin or script. They might, or might not, have a .pl extension. These
      files might, or might not, contain a Pod documentation.

      You can also add scripts in additional locations, e.g. in maint to
      the list of files to be tested with your author tests.

      * module

      These are Perl modules. For most distributions they live in the lib
      directory. Normally they have a .pm extension. These files might, or
      might not, contain a Pod documentation.

      * pod

      This is for Pod files. Normally they end in .pod. Your scripts or
      modules which contain Pod documentation are not of type pod.

      * test

      This is for test files. These files normally have a .t extension.
      Test files are also bin files.

    All file names should be in UNIX format (forward slashes as directory
    separator) as all files found by XT::Files are added in this way. If
    you add a directory or file with a different directory separator the
    result is undefined.

 Usage for author test authors

    Writing an author test with XT::Files support is straightforward. All
    you have to do is decide what kind of files your author test is going
    to test and request these files from Test::XTFiles:

        use Test::XTFiles;

        # all Perl scripts and tests
        my @files = Test::XTFiles->new->all_executable_files;

        # all modules
        my @files = Test::XTFiles->new->all_module_files;

        # all perl files (scripts, modules and tests)
        my @files = Test::XTFiles->new->all_perl_files;

        # all files with Pod in it
        use Pod::Simple::Search;
        my @files = grep { Pod::Simple::Search->new->contains_pod($_) }
            Test::XTFiles->new->all_files;

    Don't try to be clever, that's the distributions job. Ask what makes
    sense to test - it's the distributions fault if a file is not correctly
    classified. And it's much easier for a distribution author to fix the
    distributions config file then it is for the test author to guess
    correctly.

 Methods from XT::Files

    All file names passed to methods should be in UNIX format (forward
    slashes as directory separator) as all files found by XT::Files are
    added in this way. If you add a directory with a different directory
    separator the result is undefined.

 new( [ -config => CONFIG ] )

    Returns a new XT::Files object.

    Supports the -config argument which needs one of the following
    arguments.

      * undef: No configuration is loaded and the object is not
      initialized. This can be useful if you would like to build up your
      configuration programmatically.

      * A file name: The file is opened and the configuration is read from
      this file.

      * A reference to a string: The configuration is read from this
      string.

    Note: This does neither create the XT::Files singleton nor return it.
    This is probably not what you want. Unless you know exactly why you
    need a XT::Files object that differs from the singleton you should use
    initialize or instance which both create and return the singleton.

 initialize ( [ -config => CONFIG ] )

    Checks if the singleton exists and croaks if it does. Otherwise calls
    new with the same arguments and saves the XT::Files object returned by
    new in the singleton, before returning it.

    This is most likely the initialization you should use in your .t file
    if you need the object.

        my $xt = XT::Files->initialize;
        $xt->bin_file('maint/cleanup.pl');

 instance

    Checks if the XT::Files singleton exists and calls initialize without
    arguments if it does not. Then returns the singleton.

    This method silently discards all arguments. If the singleton does not
    exist, it will always use the default configuration which is the
    XT::Files config file or, if that does not exist, the
    XT::Files::Plugin::Default plugin.

    This is the method that is called by Test::XTFiles's new method.

 files

    Returns all files to be tested as XT::Files::File objects.

    You should probably use one or multiple of the methods of Test::XTFiles
    if you need to obtain a list of files to be tested, either in a Test
    test or in a .t test file.

 exclude( PATTERN )

    Adds an exclude pattern. The files method tries to match the basename
    of every file against these patterns and skips the file if it matches.

    Use this to exclude temporary or backup files you have in your
    workspace.

 bin_dir( DIRECTORY )

    Scans the directory for files and adds them all as executable files.
    Files that already have an entry are skipped.

    There are no further checks that every file in the directory is a Perl
    script. Use this method to add directories like bin or script.

    If you have a directory that contains Perl scripts and other files, add
    them selectively with bin_file from within your .t test file or use the
    XT::Files::Plugin::Files plugin from your configuration file.

 module_dir( DIRECTORY )

    Scans the directory for files and adds all files ending in .pm as
    module file and every file ending in .pod as pod file. Other files are
    skipped. Files that already have an entry are skipped.

 test_dir( DIRECTORY )

    Scans the directory for files and adds all files anding in .t as test
    file. Other files are skipped. Files that already have an entry are
    skipped.

 bin_file( FILENAME )

    Adds the file FILENAME to the list of files to be tested and marks it
    as a Perl script file. If there is already an entry for FILENAME, the
    existing entry is replaced with a new entry.

 ignore_file( FILENAME )

    Ignores a file from being tested. This method adds an undef entry for
    FILENAME. Use this to e.g. remove a single file from a directory:

        $xt->bin_dir('maint');
        $xt->ignore_file('maint/bugs.csv');

 module_file( FILENAME )

    Adds the file FILENAME to the list of files to be tested and marks it
    as a Perl module file. If there is already an entry for FILENAME, the
    existing entry is replaced with a new entry.

 pod_file( FILENAME )

    Adds the file FILENAME to the list of files to be tested and marks it
    as a Pod file. If there is already an entry for FILENAME, the existing
    entry is replaced with a new entry.

    A Pod file is a file which typically ends in .pod. This is not for
    other files (e.g. modules or scripts) that also contain Pod.

 remove_file( FILENAME )

    Removes the entry for FILENAME from the list of files to be tested.

    This differs from ignore_file in that later calls to the *_dir methods
    can add a new file for a removed file, but not for an ignored file.

 test_file( FILENAME )

    Adds the file FILENAME to the list of files to be tested and marks it
    as a test file. If there is already an entry for FILENAME, the existing
    entry is replaced with a new entry.

 file( FILENAME, [ FILE OBJECT ] )

    Returns the file entry for FILENAME when called with a single argument.

    With two arguments, the FILE OBJECT must either be undef or a
    XT::Files::File object.

    You should probably use one of the existing *_file methods to add new
    files but this method can be used to e.g. add a modulino.

        my $file = XT::Files::File->new(
            name => 'bin/my_modulino',
            is_module => 1,
            is_script => 1
        );
        $xt->file($file->name, $file);

 plugin( NAME, VERSION, KEYVALS_REF )

    Loads and runs a plugin. All plugins must have a new and a run method.

    If the name starts with a =, the leading = is removed and the remaining
    string is used as package name. Otherwise XT::Files::Plugin:: is
    prepended to the string and this is used as package name.

    The plugin method uses Module::Load to load the plugin. If a VERSION is
    defined it checks that versions parse of the VERSION isn't lower then
    the plugins version. VERSION can be undef which means every version is
    accepted.

    Then it calls the plugins new method and passes $self as the xtf
    argument and expects an object of the plugin in return.

        my $plugin_object = NAME->new( xtf => $self );

    After that it calls the plugins run method and passes it the
    KEYVALS_REF.

EXAMPLES

 Example 1 Use a test that supports XT::Files with default config

    Because the Test::Pod::Links supports XT::Files we can just use the
    following two lines for our author test .t file.

        use Test::Pod::Links 0.003;

        all_pod_files_ok();

    When Test::Pod::Links asks XT::Files for all the pod files to check,
    XT::Files checks if the distribution has an XT::Files config file. If
    the config file exists it is parsed and processed, otherwise the
    XT::Files::Plugin::Default is loaded to load the default XT::Files
    configuration.

 Example 2 Use a test that supports XT::Files with default config files

    In your distribution's .xtfilesrc or xtfiles.ini file you can configure
    the structure of your distribution.

        [Default]
        dirs=0

        [Dirs]
        bin = bin
        module = lib
        test = t
        test = xt

    The run the test the same as in Example 1

        use Test::Pod::Links

        all_pod_files_ok();

    But this time the file list is generated depending on your config file
    and not on the defaults from the XT::Files::Plugin::Default plugin.

 Example 3 Use a test that supports XT::Files but ignore default config
 file

    The following example lets you programmatically configure the XT::Files
    file list omitting a config file, if it exists and only loading the
    excludes config from the XT::Files::Plugin::Default plugin.

    We recommend that you always configure XT::Files with a config file but
    this example could be used if some special logic is required.

        use XT::Files;
        use Test::Pod::Links

        my $xt = XT::Files->initialize( -config => undef );

        $xt->plugin( 'Default', undef, [ dirs => 0 ] );

        $xt->bin_dir('bin');
        $xt->lib_dir('lib');
        $xt->test_dir('t');
        $xt->test_dir('xt');

        all_pod_files_ok();

 Example 4 Use a test that supports XT::Files with the config file but add
 test directory

    This initializes the config, either from the config file or, if no
    config file exists, with the XT::Files::Plugin::Default plugin. Then it
    adds an additional two directories. This can be used if you want to
    check some files with only some author tests.

        use XT::Files;
        use Test::Pod::Links

        my $xt = XT::Files->instance;
        $xt->test_dir('t');
        $xt->test_dir('xt');

        all_pod_files_ok();

 Example 5 Use a test that does not support XT::Files

    If a test does not support XT::Files we have to fall back to the old
    iterating over the files and call the files_ok (or similar) function.
    This allows us to use the same logic to generate the file list as all
    tests that support XT::Files use.

        use Test::More 0.88;
        use Test::XTFiles;
        use Test::Something;

        for my $file (Test::XTFiles->new->all_files()) {
          files_ok($file);
        }

        done_testing();

SEE ALSO

    Test::XTFiles, XT::Files::File, XT::Files::Plugin::Default,
    XT::Files::Plugin::Dirs, XT::Files::Plugin::Excludes,
    XT::Files::Plugin::Files, XT::Files::Plugin::lib, XT::Files::Plugin,
    XT::Files::Role::Logger

SUPPORT

 Bugs / Feature Requests

    Please report any bugs or feature requests through the issue tracker at
    https://github.com/skirmess/XT-Files/issues. You will be notified
    automatically of any progress on your issue.

 Source Code

    This is open source software. The code repository is available for
    public review and contribution under the terms of the license.

    https://github.com/skirmess/XT-Files

      git clone https://github.com/skirmess/XT-Files.git

AUTHOR

    Sven Kirmess <sven.kirmess@kzone.ch>

COPYRIGHT AND LICENSE

    This software is Copyright (c) 2018-2019 by Sven Kirmess.

    This is free software, licensed under:

      The (two-clause) FreeBSD License

