Am 30.09.2013 um 20:03 schrieb Tim Bunce <tim.bu...@pobox.com>:

> On Mon, Sep 30, 2013 at 08:52:04AM +0200, Jens Rehsack wrote:
>> 
>> Am 29.09.2013 um 21:26 schrieb Tim Bunce <tim.bu...@pobox.com>:
>> 
>>> The DBI adopted an approach towards testing 'variants' by creating extra
>>> test files that act as wrappers around existing test files.
>>> 
>>> The wrappers modify the process in some way, such as setting environment
>>> variables, before executing the original test file.
>>> 
>>> It works well, and the DBIT has adopted the same approach.
>>> 
>>> I think the approach is good and more widely applicable than just the DBI.
>>> 
>>> I'd like to propose that we factor it out into a separate distribution.
>>> 
>>> Thoughts?
>> 
>> 
>> I had the same idea - even several separate distributions, but I rejected
>> myself there for following reasons:
>> 
>> 1) The variants of the driver result in an n choose k combination
>> 2) The driver attributes (eg. list of dbm backends, list of mldbm 
>> serializers)
>>   result in a cross product of those vectors.
>> 
>> When making separate distributions, 1st approach would be to create a really
>> generic combinatorics distribution. There are some, but all currently have
>> drawbacks. This distribution would likely develop an own life (combinatoric
>> problems tend to become complex and require lot of performance speed ups).
>> 
>> Based on that Math::Fast::Combi (*gg*) Test::MakeVariantTesTFiles would
>> require exactly to know what shall be done where.
> 
> I think it just requires a callback to prune combinations that aren't wanted.

That callback can be complicated and the decision can be made at several points:

* configuration definition
* test case
* datasource configurator (DSN::Provider, Test::Database)

The routing of those decision callbacks could be somewhat complicated but
with some effort reasonable.

>> I think - from the current point of view, this would result in an over
>> complex API. Maybe sourcing out the combinatoric algorithms would clean
>> up the code a bit and later when we know better we can additionally create
>> a distributions for computing variants (combinations, variations, 
>> permutations,
>> cross products, …) and based on that ?
> 
> I think a clean simple API could be designed. Keeping the test rewriting
> logic separate simplifies the rest of DBIT. It's a Separation Of Concerns.
> 
> Here's a rough suggestion for an API:
> 
>    write_variants(
>        # required:
>        test_files => [
>            't/foo.t', ...
>        ],
>        variants => {
>            wibble => { ... },
>            wobble => { ... },
>        },
>        # optional:
>        filter => sub {
>            my ($test_file, $variant_set) = @_;
>            delete $variant_set->{wibble} if ...;
>            return [ %$variant_set ]
>        }
>    );
> 
> The write_variants sub would call the filter callback for every combination
> of variants (in this example: wibble alone, wobble alone, wibble + wobble).

And for "none" ;)

> The filter can return zero or more array refs where each array contains
> the variants to be applied, in order. Returning nothing means don't
> create variants for that test. Returning multiple items makes it easy
> for the filter to generate extra permutations if appropriate for some tests.
> 
> What's missing?

Short answer: More levels and driver tunable settings. I give you a longer
example call (of the currently supported and implemented variants - beside
the filter callback - DBI::Test::Conf can populate):

    write_variants(
        # required:
        test_cases => {
            foo => '@BEGIN@
do "t/foo.t"
@END@',
            bar => '@BEGIN@
do "t/bar.t"
@END@',
        },
        variants => {
                     dbi => {
                              pureperl => {
                                            name         => "DBI::PurePerl",
                                            category     => "dbi",
                                            cat_abbrev   => "z",
                                            abbrev       => "p",
                                            init_stub    => [ 
'$ENV{DBI_PUREPERL} = 2', ],
                                            cleanup_stub => ['delete 
$ENV{DBI_PUREPERL};'],
                                          },
                            },
                     dialect => {
                                  ansi_sql => {
                                                name         => "ANSI SQL",
                                                category     => "ansi",
                                                cat_abbrev   => "l",
                                                abbrev       => "a",
                                                init_stub    => [ '...', ],
                                                cleanup_stub => ['...'],
                                              },
                                },
                     proxy => {
                         gofer => {
                             name       => "DBD::Gofer",
                             category   => "dbi",
                             cat_abbrev => "z",
                             abbrev     => "g",
                             init_stub =>
                               [ q{$ENV{DBI_AUTOPROXY} = 
'dbi:Gofer:transport=null;policy=pedantic'}, ],
                             cleanup_stub => [q|delete $ENV{DBI_AUTOPROXY};|],
                         },
                     },
                     sql_engine => {
                                     nano => {
                                               name         => "DBI::SQL::Nano",
                                               category     => "dbi",
                                               cat_abbrev   => "z",
                                               abbrev       => "n",
                                               init_stub    => [ 
q{$ENV{DBI_SQL_NANO} = 1}, ],
                                               cleanup_stub => [q|delete 
$ENV{DBI_SQL_NANO};|],
                                             },
                                   }
                    },
        drivers => {
                     dbm => {
                              category   => "driver",
                              cat_abbrev => "d",
                              abbrev     => "d",
                              driver     => "dbi:DBM:",
                              variants   => {
                                            mldbm => {
                                                       f => { dbm_mldbm => 
'FreezeThaw' },
                                                       d => { dbm_mldbm => 
'Data::Dumper' },
                                                       s => { dbm_mldbm => 
'Storable' },
                                                       # … JSON, YAML
                                                     },
                                            type => {
                                                      s => { dbm_type => 
'SDBM_File' },
                                                      g => { dbm_type => 
'GDBM_File' },
                                                      d => { dbm_type => 
'DB_File' },
                                                      b => {
                                                             dbm_type           
=> 'BerkeleyDB',
                                                             dbm_berkeley_flags 
=> '...'
                                                           }
                                                    },
                                          },
                              name => "DSN for DBM",
                            },
                     csv => {
                              category   => "driver",
                              cat_abbrev => "d",
                              abbrev     => "c",
                              driver     => "dbi:CSV:",
                              variants   => {
                                            type => {
                                                      p => { csv_class => 
'Text::CSV' },
                                                      x => { csv_class => 
'Text::CSV_XS' },
                                                    },
                                          },
                              name => "DSN for CSV",
                            },
                   },
        # optional:
        filter => sub {
            my ( $test_file, $variant_set ) = @_;
            delete $variant_set->{wibble} if ...;
            return [%$variant_set];
        }
    );

Cheers
-- 
Jens Rehsack
pkgsrc, Perl5
rehs...@cpan.org



Reply via email to