=pod

=head1 NAME

App::Prove::Plugin::TestArgs - A prove plugin to configure test aliases and
arguments

=head1 SYNOPSIS

  # t/config.yml
  ---
  t/foo.t:
    - alias: "foo once"
      args:  [ABC, DEF]
    - alias: "foo twice"
    - alias: "foo thrice"
      args:  [GHI]

  # command-line 
  prove -PTestArgs=t/config.yml --verbose t/foo.t t/bar.t :: UVW XYZ
  foo once ....
  1..1
  # ['ABC','DEF']
  ok 1 - t/foo.t
  ok
  foo twice ...
  1..1
  # ['UVW','XYZ']
  ok 1 - t/foo.t
  ok
  foo thrice ..
  1..1
  # ['GHI']
  ok 1 - t/foo.t
  ok
  t/bar.t .....
  1..1
  # ['UVW','XYZ']
  ok 1 - t/bar.t
  ok
  All tests successful.
  Files=4, Tests=4,  0 wallclock secs ( 0.01 usr  0.01 sys +  0.03 cusr  0.00 csys =  0.05 CPU)
  Result: PASS

=head1 DESCRIPTION

L<TAP::Harness> is the default test harness of the C<prove> command-line test
driver program. The harness has a C<test_args> object attribute that allows us
to pass different arguments to test scripts. Furthermore the harness
C<runtests()> object method implementation helps us to run a test script
multiple times giving each run a unique test name (an C<alias>).  Unfortunately
it seems to be impossible to control this feature directly via the C<prove>
command-line interface. C<prove> uses the full path to the test script as the
test name in its test output.

This plugin allows us to assign multiple C<alias>-C<args> mappings to a test
script.  Each mapping triggers a separate run of the test script. The C<args>
key of a mapping is optional. If it is missing, C<prove>'s own optional test
script arguments, passed at the command-line after an arisdottle (C<::>), are
used as a default.

For the time being the configuration has to be stored in a YAML file that is
the only argument passed to this plugin.

C<prove>'s test output no longer shows the test script names, if test aliases
are configured. As of version C<2.1.0> this plugin provides an alternative
configuration scheme that helps us to overcome this drawback.

  # t/config_name_scripts.yml
  ---
  name: "%s (%a)"
  scripts:
    t/foo.t:
      - alias: "foo once"
        args:  [ABC, DEF]
      - alias: "foo twice"
      - alias: "foo thrice"
        args:  [GHI]

  # command-line 
  prove -PTestArgs=t/config_name_scripts.yml --verbose t/foo.t t/bar.t :: UVW XYZ
  t/foo.t (foo once) ....
  1..1
  # ['ABC','DEF']
  ok 1 - t/foo.t
  ok
  t/foo.t (foo twice) ...
  1..1
  # ['UVW','XYZ']
  ok 1 - t/foo.t
  ok
  t/foo.t (foo thrice) ..
  1..1
  # ['GHI']
  ok 1 - t/foo.t
  ok
  t/bar.t ...............
  1..1
  # ['UVW','XYZ']
  ok 1 - t/bar.t
  ok
  All tests successful.
  Files=4, Tests=4,  0 wallclock secs ( 0.02 usr  0.01 sys +  0.15 cusr  0.02 csys =  0.20 CPU)
  Result: PASS

The C<scripts> key points to the test scripts mapping. The C<name> key points
to a L<sprintf|perlfunc/"sprintf FORMAT, LIST"> like format. The allowed
conversions are C<%s> (full path to the test script) and C<%a> (test alias).
The format tells C<prove> what to use as the test name in its test output. The
C<name> key is optional. If it is omitted the C<scripts> key can be omitted too
and this brings us back to the original configuration scheme.

=head1 CAVEAT

Note that a key of the C<scripts> mapping is recognized only, if it is equal to
one of the test scripts collected by C<prove>. Counterexample: If I<t/foo.t> is
one of the keys of the C<scripts> mapping and I<./t/foo.t> is the test script
passed to C<prove> the I<./> prefix is the significant difference. I was not
able yet to implement an improved version of this plugin that overcomes this
weakness.

=head1 AUTHOR

Sven Willenbuecher, E<lt>sven.willenbuecher@gmx.deE<gt>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2024 by Sven Willenbuecher.

This is free software; you can redistribute it and/or modify it under the same
terms as the Perl 5 programming language system itself.

=cut
