Re: Proposal: Test::MakeVariantTestFiles

Jens Rehsack <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.dbi.sybase.devel
Message-ID <[email protected]>
Am 30.09.2013 um 20:03 schrieb Tim Bunce <[email protected]>:

> On Mon, Sep 30, 2013 at 08:52:04AM +0200, Jens Rehsack wrote:
>> 
>> Am 29.09.2013 um 21:26 schrieb Tim Bunce <[email protected]>:
>> 
>>> 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
[email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.