Jens Rehsack > Test-WriteVariants-0.010 > Test::WriteVariants



Annotate this POD


View/Report Bugs
Module Version: 0.010   Source  


Test::WriteVariants - Dynamic generation of tests in nested combinations of contexts


    use Test::WriteVariants;

    my $test_writer = Test::WriteVariants->new();


        # tests we want to run in various contexts
        input_tests => {
            'core/10-foo' => { require => 't/core/10-foo.t' },
            'core/20-bar' => { require => 't/core/20-bar.t' },

        # one or more providers of variant contexts
        variant_providers => [
            sub {
                my ($path, $context, $tests) = @_;
                my %variants = (
                    plain    => $context->new_env_var(MY_MODULE_PUREPERL => 0),
                    pureperl => $context->new_env_var(MY_MODULE_PUREPERL => 1),
                return %variants;
            sub {
                my ($path, $context, $tests) = @_;
                my %variants = map {
                    $_ => $context->new_env_var(MY_MODULE_WIBBLE => $_),
                } 1..3;
                delete $variants{3} if $context->get_env_var("MY_MODULE_PUREPERL");
                return %variants;

        # where to generate the .t files that wrap the input_tests
        output_dir => 't/variants',

When run that generates the desired test variants:

    Writing t/variants/plain/1/core/10-foo.t
    Writing t/variants/plain/1/core/20-bar.t
    Writing t/variants/plain/2/core/10-foo.t
    Writing t/variants/plain/2/core/20-bar.t
    Writing t/variants/plain/3/core/10-foo.t
    Writing t/variants/plain/3/core/20-bar.t
    Writing t/variants/pureperl/1/core/10-foo.t
    Writing t/variants/pureperl/1/core/20-bar.t
    Writing t/variants/pureperl/2/core/10-foo.t
    Writing t/variants/pureperl/2/core/20-bar.t

Here's what t/variants/pureperl/2/core/20-bar.t looks like:

    END { delete $ENV{MY_MODULE_WIBBLE} } # for VMS
    END { delete $ENV{MY_MODULE_PUREPERL} } # for VMS
    require 't/core/20-bar.t';

Here's an example that uses plugins to provide the tests and the variants:

    my $test_writer = Test::WriteVariants->new();

    # gather set of input tests that we want to run in various contexts
    # these can come from various sources, including modules and test files
    my $input_tests = $test_writer->find_input_test_modules(
        search_path => [ 'DBI::TestCase' ]


        # tests we want to run in various contexts
        input_tests => $input_tests,

        # one or more providers of variant contexts
        # (these can be code refs or plugin namespaces)
        variant_providers => [

        # where to generate the .t files that wrap the input_tests
        output_dir => $output_dir,


NOTE: This is alpha code that's still evolving - nothing is stable.

See List::MoreUtils (on github) for an example use.



    $test_writer = Test::WriteVariants->new(%attributes);

Instanciates a Test::WriteVariants instance and sets the specified attributes, if any.


    $bool = $test_writer->allow_dir_overwrite;

If the output directory already exists when tumble() is called it'll throw an exception (and warn if it wasn't created during the run). Setting allow_dir_overwrite true disables this safety check.


    $bool = $test_writer->allow_file_overwrite;

If the test file that's about to be written already exists then write_output_files() will throw an exception. Setting allow_file_overwrite true disables this safety check.


        input_tests => \%input_tests,
        variant_providers => \@variant_providers,
        output_dir => $output_dir,

Instanciates a Data::Tumbler. Sets its consumer to call:

    $self->write_output_files($path, $context, $payload, $output_dir)

and sets its add_context to call:

    $context->new($context, $item);

and then calls its tumble method:



    $input_tests = $test_writer->find_input_test_modules(


Not yet implemented - will file .t files.


        $input_tests,   # the \%input_tests to add the test module to
        $test_name,     # the key to use in \%input_tests
        $test_spec      # the details of the test file

Adds the $test_spec to %$input_tests keys by $test_name. In other words:

    $input_tests->{ $test_name } = $test_spec;

An exception will be thrown if a test with $test_name already exists in %$input_tests.

This is a low-level interface that's not usually called directly. See "add_test_module".


        $input_tests,     # the \%input_tests to add the test module to
        $module_name,     # the package name of the test module
        $edit_test_name   # a code ref to edit the test module name in $_


    $providers = $test_writer->normalize_providers($providers);

Given a reference to an array of providers, returns a reference to a new array. Any code references in the original array are passed through unchanged.

Any other value is treated as a package name and passed to Module::Pluggable::Object as a namespace search_path to find plugins. An exception is thrown if no plugins are found.

The corresponding element of the original $providers array is replaced with a new provider code reference which calls the provider_initial, provider, and provider_final methods, if present, for each plugin namespace in turn.

Normal Data::Tumbler provider subroutines are called with these arguments:

    ($path, $context, $tests)

and the return value is expected to be a hash. Whereas the plugin provider methods are called with these arguments:

    ($test_writer, $path, $context, $tests, $variants)

and the return value is ignored. The $variants argument is a reference to a hash that will be returned to Data::Tumbler and which should be edited by the plugin provider method. This allows a plugin to see, and change, the variants requested by any other plugins that have already been run for this provider.


    $test_writer->write_output_files($path, $context, $input_tests, $output_dir);

Writes test files for each test in %$input_tests, for the given $path and $context, into the $output_dir.

The $output_dir, @$path, and key of %$input_tests are concatenated to form a file name. A ".t" is added if not already present.

Calls "get_test_file_body" to get the content of the test file, and then calls "write_file" to write it.


    $test_writer->write_file($filepath, $content);

Throws an exception if $filepath already exists and "allow_file_overwrite" is not true.

Creates $filepath and writes $content to it. Creates any directories that are needed. Throws an exception on error.


    $test_body = $test_writer->get_test_file_body($context, $test_spec);

XXX This should probably be a method call on an object instanciated by the find_input_test_* methods.


This program is free software; you can redistribute it and/or modify it under the terms of either:

        a) the GNU General Public License as published by the Free
        Software Foundation; either version 1, or (at your option) any
        later version, or

        b) the "Artistic License" which comes with this Kit.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the Artistic License for more details.

syntax highlighting: