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