1Test::MockRandom(3)   User Contributed Perl Documentation  Test::MockRandom(3)
2
3
4

NAME

6       Test::MockRandom - Replaces random number generation with non-random
7       number generation
8

VERSION

10       version 1.01
11

SYNOPSIS

13          # intercept rand in another package
14          use Test::MockRandom 'Some::Other::Package';
15          use Some::Other::Package; # exports sub foo { return rand }
16          srand(0.13);
17          foo(); # returns 0.13
18
19          # using a seed list and "oneish"
20          srand(0.23, 0.34, oneish() );
21          foo(); # returns 0.23
22          foo(); # returns 0.34
23          foo(); # returns a number just barely less than one
24          foo(); # returns 0, as the seed array is empty
25
26          # object-oriented, for use in the current package
27          use Test::MockRandom ();
28          my $nrng = Test::MockRandom->new(0.42, 0.23);
29          $nrng->rand(); # returns 0.42
30

DESCRIPTION

32       This perhaps ridiculous-seeming module was created to test routines
33       that manipulate random numbers by providing a known output from "rand".
34       Given a list of seeds with "srand", it will return each in turn.  After
35       seeded random numbers are exhausted, it will always return 0.  Seed
36       numbers must be of a form that meets the expected output from "rand" as
37       called with no arguments -- i.e.  they must be between 0 (inclusive)
38       and 1 (exclusive).  In order to facilitate generating and testing a
39       nearly-one number, this module exports the function "oneish", which
40       returns a number just fractionally less than one.
41
42       Depending on how this module is called with "use", it will export
43       "rand" to a specified package (e.g. a class being tested) effectively
44       overriding and intercepting calls in that package to the built-in
45       "rand".  It can also override "rand" in the current package or even
46       globally.  In all of these cases, it also exports "srand" and "oneish"
47       to the current package in order to control the output of "rand".  See
48       "USAGE" for details.
49
50       Alternatively, this module can be used to generate objects, with each
51       object maintaining its own distinct seed array.
52

USAGE

54       By default, Test::MockRandom does not export any functions.  This still
55       allows object-oriented use by calling "Test::MockRandom->new(@seeds)".
56       In order for Test::MockRandom to be more useful, arguments must be
57       provided during the call to "use".
58
59   use Test::MockRandom 'Target::Package'
60       The simplest way to intercept "rand" in another package is to provide
61       the name(s) of the package(s) for interception as arguments in the
62       "use" statement.  This will export "rand" to the listed packages and
63       will export "srand" and "oneish" to the current package to control the
64       behavior of "rand".  You must "use" Test::MockRandom before you "use"
65       the target package.  This is a typical case for testing a module that
66       uses random numbers:
67
68         use Test::More 'no_plan';
69         use Test::MockRandom 'Some::Package';
70         BEGIN { use_ok( Some::Package ) }
71
72         # assume sub foo { return rand } was imported from Some::Package
73
74         srand(0.5)
75         is( foo(), 0.5, "is foo() 0.5?") # test gives "ok"
76
77       If multiple package names are specified, "rand" will be exported to all
78       of them.
79
80       If you wish to export "rand" to the current package, simply provide
81       "__PACKAGE__" as the parameter for "use", or "main" if importing to a
82       script without a specified package.  This can be part of a list
83       provided to "use".  All of the following idioms work:
84
85         use Test::MockRandom qw( main Some::Package ); # Assumes a script
86         use Test::MockRandom __PACKAGE__, 'Some::Package';
87
88         # The following doesn't interpolate __PACKAGE__ as above, but
89         # Test::MockRandom will still DWIM and handle it correctly
90
91         use Test::MockRandom qw( __PACKAGE__ Some::Package );
92
93   use Test::MockRandom %customized
94       As an alternative to a package name as an argument to "use",
95       Test::MockRandom will also accept a hash reference with a custom set of
96       instructions for how to export functions:
97
98         use Test::MockRandom {
99            rand   => [ Some::Package, {Another::Package => 'random'} ],
100            srand  => { Another::Package => 'seed' },
101            oneish => __PACKAGE__
102         };
103
104       The keys of the hash may be any of "rand", "srand", and "oneish".  The
105       values of the hash give instructions for where to export the symbol
106       corresponding to the key.  These are interpreted as follows, depending
107       on their type:
108
109       •   String: a package to which Test::MockRandom will export the symbol
110
111       •   Hash Reference: the key is the package to which Test::MockRandom
112           will export the symbol and the value is the name under which it
113           will be exported
114
115       •   Array Reference: a list of strings or hash references which will be
116           handled as above
117
118   Test::MockRandom->export_rand_to()
119       In order to intercept the built-in "rand" in another package,
120       Test::MockRandom must export its own "rand" function to the target
121       package before the target package is compiled, thus overriding calls to
122       the built-in.  The simple approach (described above) of providing the
123       target package name in the "use Test::MockRandom" statement
124       accomplishes this because "use" is equivalent to a "require" and
125       "import" within a "BEGIN" block.  To explicitly intercept "rand" in
126       another package, you can also call "export_rand_to", but it must be
127       enclosed in a "BEGIN" block of its own.  The explicit form also support
128       function aliasing just as with the custom approach with "use",
129       described above:
130
131         use Test::MockRandom;
132         BEGIN {Test::MockRandom->export_rand_to('AnotherPackage'=>'random')}
133         use AnotherPackage;
134
135       This "BEGIN" block must not include a "use" statement for the package
136       to be intercepted, or perl will compile the package to be intercepted
137       before the "export_rand_to" function has a chance to execute and
138       intercept calls to the built-in "rand".  This is very important in
139       testing.  The "export_rand_to" call must be in a separate "BEGIN" block
140       from a "use" or "use_ok" test, which should be enclosed in a "BEGIN"
141       block of its own:
142
143         use Test::More tests => 1;
144         use Test::MockRandom;
145         BEGIN { Test::MockRandom->export_rand_to( 'AnotherPackage' ); }
146         BEGIN { use_ok( 'AnotherPackage' ); }
147
148       Given these cautions, it's probably best to use either the simple or
149       custom approach with "use", which does the right thing in most
150       circumstances.  Should additional explicit customization be necessary,
151       Test::MockRandom also provides "export_srand_to" and
152       "export_oneish_to".
153
154   Overriding "rand" globally: use Test::MockRandom 'CORE::GLOBAL'
155       This is just like intercepting "rand" in a package, except that you do
156       it globally by overriding the built-in function in "CORE::GLOBAL".
157
158         use Test::MockRandom 'CORE::GLOBAL';
159
160         # or
161
162         BEGIN { Test::MockRandom->export_rand_to('CORE::GLOBAL') }
163
164       You can always access the real, built-in "rand" by calling it
165       explicitly as "CORE::rand".
166
167   Intercepting "rand" in a package that also contains a "rand" function
168       This is tricky as the order in which the symbol table is manipulated
169       will lead to very different results.  This can be done safely (maybe)
170       if the module uses the same rand syntax/prototype as the system call
171       but offers them up as method calls which resolve at run-time instead of
172       compile time.  In this case, you will need to do an explicit intercept
173       (as above) but do it after importing the package.  I.e.:
174
175         use Test::MockRandom 'SomeRandPackage';
176         use SomeRandPackage;
177         BEGIN { Test::MockRandom->export_rand_to('SomeRandPackage');
178
179       The first line is necessary to get "srand" and "oneish" exported to the
180       current package.  The second line will define a "sub rand" in
181       "SomeRandPackage", overriding the results of the first line.  The third
182       line then re-overrides the "rand".  You may see warnings about "rand"
183       being redefined.
184
185       Depending on how your "rand" is written and used, there is a good
186       likelihood that this isn't going to do what you're expecting, no matter
187       what.  If your package that defines "rand" relies internally upon the
188       system "CORE::GLOBAL::rand" function, then you may be best off
189       overriding that instead.
190

FUNCTIONS

192   "new"
193         $obj = new( LIST OF SEEDS );
194
195       Returns a new Test::MockRandom object with the specified list of seeds.
196
197   "srand"
198         srand( LIST OF SEEDS );
199         $obj->srand( LIST OF SEEDS);
200
201       If called as a bare function call or package method, sets the seed list
202       for bare/package calls to "rand".  If called as an object method, sets
203       the seed list for that object only.
204
205   "rand"
206         $rv = rand();
207         $rv = $obj->rand();
208         $rv = rand(3);
209
210       If called as a bare or package function, returns the next value from
211       the package seed list.  If called as an object method, returns the next
212       value from the object seed list.
213
214       If "rand" is called with a numeric argument, it follows the same
215       behavior as the built-in function -- it multiplies the argument with
216       the next value from the seed array (resulting in a random fractional
217       value between 0 and the argument, just like the built-in).  If the
218       argument is 0, undef, or non-numeric, it is treated as if the argument
219       is 1.
220
221       Using this with an argument in testing may be complicated, as limits in
222       floating point precision mean that direct numeric comparisons are not
223       reliable.  E.g.
224
225         srand(1/3);
226         rand(3);       # does this return 1.0 or .999999999 etc.
227
228   "oneish"
229         srand( oneish() );
230         if ( rand() == oneish() ) { print "It's almost one." };
231
232       A utility function to return a nearly-one value.  Equal to ( 2^32 - 1 )
233       / 2^32.  Useful in "srand" and test functions.
234
235   "export_rand_to"
236         Test::MockRandom->export_rand_to( 'Some::Class' );
237         Test::MockRandom->export_rand_to( 'Some::Class' => 'random' );
238
239       This function exports "rand" into the specified package namespace.  It
240       must be called as a class function.  If a second argument is provided,
241       it is taken as the symbol name used in the other package as the alias
242       to "rand":
243
244         use Test::MockRandom;
245         BEGIN { Test::MockRandom->export_rand_to( 'Some::Class' => 'random' ); }
246         use Some::Class;
247         srand (0.5);
248         print Some::Class::random(); # prints 0.5
249
250       It can also be used to explicitly intercept "rand" after
251       Test::MockRandom has been loaded.  The effect of this function is
252       highly dependent on when it is called in the compile cycle and should
253       usually called from within a BEGIN block.  See "USAGE" for details.
254
255       Most users will not need this function.
256
257   "export_srand_to"
258         Test::MockRandom->export_srand_to( 'Some::Class' );
259         Test::MockRandom->export_srand_to( 'Some::Class' => 'seed' );
260
261       This function exports "srand" into the specified package namespace.  It
262       must be called as a class function.  If a second argument is provided,
263       it is taken as the symbol name to use in the other package as the alias
264       for "srand".  This function may be useful if another package wraps
265       "srand":
266
267         # In Some/Class.pm
268         package Some::Class;
269         sub seed { srand(shift) }
270         sub foo  { rand }
271
272         # In a script
273         use Test::MockRandom 'Some::Class';
274         BEGIN { Test::MockRandom->export_srand_to( 'Some::Class' ); }
275         use Some::Class;
276         seed(0.5);
277         print foo();   # prints "0.5"
278
279       The effect of this function is highly dependent on when it is called in
280       the compile cycle and should usually be called from within a BEGIN
281       block.  See "USAGE" for details.
282
283       Most users will not need this function.
284
285   "export_oneish_to"
286         Test::MockRandom->export_oneish_to( 'Some::Class' );
287         Test::MockRandom->export_oneish_to( 'Some::Class' => 'nearly_one' );
288
289       This function exports "oneish" into the specified package namespace.
290       It must be called as a class function.  If a second argument is
291       provided, it is taken as the symbol name to use in the other package as
292       the alias for "oneish".  Since "oneish" is usually only used in a test
293       script, this function is likely only necessary to alias "oneish" to
294       some other name in the current package:
295
296         use Test::MockRandom 'Some::Class';
297         BEGIN { Test::MockRandom->export_oneish_to( __PACKAGE__, "one" ); }
298         use Some::Class;
299         seed( one() );
300         print foo();   # prints a value very close to one
301
302       The effect of this function is highly dependent on when it is called in
303       the compile cycle and should usually be called from within a BEGIN
304       block.  See "USAGE" for details.
305
306       Most users will not need this function.
307

SEE ALSO

309       •   Test::MockObject
310
311       •   Test::MockModule
312

SUPPORT

314   Bugs / Feature Requests
315       Please report any bugs or feature requests through the issue tracker at
316       <https://github.com/dagolden/Test-MockRandom/issues>.  You will be
317       notified automatically of any progress on your issue.
318
319   Source Code
320       This is open source software.  The code repository is available for
321       public review and contribution under the terms of the license.
322
323       <https://github.com/dagolden/Test-MockRandom>
324
325         git clone https://github.com/dagolden/Test-MockRandom.git
326

AUTHOR

328       David Golden <dagolden@cpan.org>
329
331       This software is Copyright (c) 2014 by David Golden.
332
333       This is free software, licensed under:
334
335         The Apache License, Version 2.0, January 2004
336
337
338
339perl v5.34.0                      2022-01-21               Test::MockRandom(3)
Impressum