1Test::WriteVariants(3)User Contributed Perl DocumentationTest::WriteVariants(3)
2
3
4
6 Test::WriteVariants - Dynamic generation of tests in nested
7 combinations of contexts
8
10 use Test::WriteVariants;
11
12 my $test_writer = Test::WriteVariants->new();
13
14 $test_writer->write_test_variants(
15
16 # tests we want to run in various contexts
17 input_tests => {
18 'core/10-foo' => { require => 't/core/10-foo.t' },
19 'core/20-bar' => { require => 't/core/20-bar.t' },
20 },
21
22 # one or more providers of variant contexts
23 variant_providers => [
24 sub {
25 my ($path, $context, $tests) = @_;
26 my %variants = (
27 plain => $context->new_env_var(MY_MODULE_PUREPERL => 0),
28 pureperl => $context->new_env_var(MY_MODULE_PUREPERL => 1),
29 );
30 return %variants;
31 },
32 sub {
33 my ($path, $context, $tests) = @_;
34 my %variants = map {
35 $_ => $context->new_env_var(MY_MODULE_WIBBLE => $_),
36 } 1..3;
37 delete $variants{3} if $context->get_env_var("MY_MODULE_PUREPERL");
38 return %variants;
39 },
40 ],
41
42 # where to generate the .t files that wrap the input_tests
43 output_dir => 't/variants',
44 );
45
46 When run that generates the desired test variants:
47
48 Writing t/variants/plain/1/core/10-foo.t
49 Writing t/variants/plain/1/core/20-bar.t
50 Writing t/variants/plain/2/core/10-foo.t
51 Writing t/variants/plain/2/core/20-bar.t
52 Writing t/variants/plain/3/core/10-foo.t
53 Writing t/variants/plain/3/core/20-bar.t
54 Writing t/variants/pureperl/1/core/10-foo.t
55 Writing t/variants/pureperl/1/core/20-bar.t
56 Writing t/variants/pureperl/2/core/10-foo.t
57 Writing t/variants/pureperl/2/core/20-bar.t
58
59 Here's what t/variants/pureperl/2/core/20-bar.t looks like:
60
61 #!perl
62 $ENV{MY_MODULE_WIBBLE} = 2;
63 END { delete $ENV{MY_MODULE_WIBBLE} } # for VMS
64 $ENV{MY_MODULE_PUREPERL} = 1;
65 END { delete $ENV{MY_MODULE_PUREPERL} } # for VMS
66 require 't/core/20-bar.t';
67
68 Here's an example that uses plugins to provide the tests and the
69 variants:
70
71 my $test_writer = Test::WriteVariants->new();
72
73 # gather set of input tests that we want to run in various contexts
74 # these can come from various sources, including modules and test files
75 my $input_tests = $test_writer->find_input_test_modules(
76 search_path => [ 'DBI::TestCase' ]
77 );
78
79 $test_writer->write_test_variants(
80
81 # tests we want to run in various contexts
82 input_tests => $input_tests,
83
84 # one or more providers of variant contexts
85 # (these can be code refs or plugin namespaces)
86 variant_providers => [
87 "DBI::Test::VariantDBI",
88 "DBI::Test::VariantDriver",
89 "DBI::Test::VariantDBD",
90 ],
91
92 # where to generate the .t files that wrap the input_tests
93 output_dir => $output_dir,
94 );
95
97 Test::WriteVariants is a utility to create variants of a common test.
98
99 Given the situation - like in DBI where some tests are the same for
100 DBI::SQL::Nano and it's drop-in replacement SQL::Statement. Or a
101 distribution duo having a Pure-Perl and an XS variant - and the same
102 test shall be used to ensure XS and PP version are really drop-in
103 replacements for each other.
104
106 new
107 $test_writer = Test::WriteVariants->new(%attributes);
108
109 Instanciates a Test::WriteVariants instance and sets the specified
110 attributes, if any.
111
112 allow_dir_overwrite
113 $test_writer->allow_dir_overwrite($bool);
114 $bool = $test_writer->allow_dir_overwrite;
115
116 If the output directory already exists when tumble() is called it'll
117 throw an exception (and warn if it wasn't created during the run).
118 Setting allow_dir_overwrite true disables this safety check.
119
120 allow_file_overwrite
121 $test_writer->allow_file_overwrite($bool);
122 $bool = $test_writer->allow_file_overwrite;
123
124 If the test file that's about to be written already exists then
125 write_output_files() will throw an exception. Setting
126 allow_file_overwrite true disables this safety check.
127
128 write_test_variants
129 $test_writer->write_test_variants(
130 input_tests => \%input_tests,
131 variant_providers => \@variant_providers,
132 output_dir => $output_dir,
133 );
134
135 Instanciates a Data::Tumbler. Sets its "consumer" to call:
136
137 $self->write_output_files($path, $context, $payload, $output_dir)
138
139 and sets its "add_context" to call:
140
141 $context->new($context, $item);
142
143 and then calls its "tumble" method:
144
145 $tumbler->tumble(
146 $self->normalize_providers($variant_providers),
147 [],
148 Test::WriteVariants::Context->new(),
149 $input_tests,
150 );
151
152 find_input_test_modules
153 $input_tests = $test_writer->find_input_test_modules(
154 search_path => ["Helper"],
155 search_dirs => "t/lib",
156 test_prefix => "Extra::Helper",
157 input_tests => $input_tests
158 );
159
160 find_input_test_files
161 Not yet implemented - will file .t files.
162
163 find_input_inline_tests
164 $input_tests = $test_writer->find_input_inline_tests(
165 search_patterns => ["*.it"],
166 search_dirs => "t/inl",
167 input_tests => $input_tests
168 );
169
170 add_test
171 $test_writer->add_test(
172 $input_tests, # the \%input_tests to add the test module to
173 $test_name, # the key to use in \%input_tests
174 $test_spec # the details of the test file
175 );
176
177 Adds the $test_spec to %$input_tests keys by $test_name. In other
178 words:
179
180 $input_tests->{ $test_name } = $test_spec;
181
182 An exception will be thrown if a test with $test_name already exists in
183 %$input_tests.
184
185 This is a low-level interface that's not usually called directly. See
186 "add_test_module".
187
188 add_test_module
189 $test_writer->add_test_module(
190 $input_tests, # the \%input_tests to add the test module to
191 $module_name, # the package name of the test module
192 $edit_test_name # a code ref to edit the test module name in $_
193 );
194
195 add_test_inline
196 $test_writer->add_test_inline(
197 $input_tests, # the \%input_tests to add the test module to
198 $file_name, # the file name of the test code to inline
199 $edit_test_name # a code ref to edit the test file name in $_
200 );
201
202 normalize_providers
203 $providers = $test_writer->normalize_providers($providers);
204
205 Given a reference to an array of providers, returns a reference to a
206 new array. Any code references in the original array are passed
207 through unchanged.
208
209 Any other value is treated as a package name and passed to
210 Module::Pluggable::Object as a namespace "search_path" to find plugins.
211 An exception is thrown if no plugins are found.
212
213 The corresponding element of the original $providers array is replaced
214 with a new provider code reference which calls the "provider_initial",
215 "provider", and "provider_final" methods, if present, for each plugin
216 namespace in turn.
217
218 Normal Data::Tumbler provider subroutines are called with these
219 arguments:
220
221 ($path, $context, $tests)
222
223 and the return value is expected to be a hash. Whereas the plugin
224 provider methods are called with these arguments:
225
226 ($test_writer, $path, $context, $tests, $variants)
227
228 and the return value is ignored. The $variants argument is a reference
229 to a hash that will be returned to Data::Tumbler and which should be
230 edited by the plugin provider method. This allows a plugin to see, and
231 change, the variants requested by any other plugins that have already
232 been run for this provider.
233
234 write_output_files
235 $test_writer->write_output_files($path, $context, $input_tests, $output_dir);
236
237 Writes test files for each test in %$input_tests, for the given $path
238 and $context, into the $output_dir.
239
240 The $output_dir, @$path, and key of %$input_tests are concatenated to
241 form a file name. A ".t" is added if not already present.
242
243 Calls "get_test_file_body" to get the content of the test file, and
244 then calls "write_file" to write it.
245
246 write_file
247 $test_writer->write_file($filepath, $content);
248
249 Throws an exception if $filepath already exists and
250 "allow_file_overwrite" is not true.
251
252 Creates $filepath and writes $content to it. Creates any directories
253 that are needed. Throws an exception on error.
254
255 get_test_file_body
256 $test_body = $test_writer->get_test_file_body($context, $test_spec);
257
258 XXX This should probably be a method call on an object instanciated by
259 the find_input_test_* methods.
260
262 Please report any bugs or feature requests to "bug-Test-WriteVariants
263 at rt.cpan.org", or through the web interface at
264 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-WriteVariants>. I
265 will be notified, and then you'll automatically be notified of progress
266 on your bug as I make changes.
267
269 You can find documentation for this module with the perldoc command.
270
271 perldoc Test::WriteVariants
272
273 You can also look for information at:
274
275 • RT: CPAN's request tracker
276
277 <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-WriteVariants>
278
279 • AnnoCPAN: Annotated CPAN documentation
280
281 <http://annocpan.org/dist/Test-WriteVariants>
282
283 • CPAN Ratings
284
285 <http://cpanratings.perl.org/d/Test-WriteVariants>
286
287 • Search CPAN
288
289 <http://search.cpan.org/dist/Test-WriteVariants/>
290
292 Tim Bunce, "<timb at cpan.org>"
293
294 Jens Rehsack, "rehsack at cpan.org"
295
297 This module has been created to support DBI::Test in design and
298 separation of concerns.
299
301 Copyright 2014-2017 Tim Bunce and Perl5 DBI Team.
302
304 This program is free software; you can redistribute it and/or modify it
305 under the terms of either:
306
307 a) the GNU General Public License as published by the Free
308 Software Foundation; either version 1, or (at your option) any
309 later version, or
310
311 b) the "Artistic License" which comes with this Kit.
312
313 This program is distributed in the hope that it will be useful, but
314 WITHOUT ANY WARRANTY; without even the implied warranty of
315 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the
316 GNU General Public License or the Artistic License for more details.
317
318
319
320perl v5.38.0 2023-07-21 Test::WriteVariants(3)