[ANNOUNCE] Test::MockRandom 0.92

From: David Golden (dg-junk_at_hyperbolic.net)
Date: 12/23/04

  • Next message: Terrence Brannon: "Re: [ANNOUNCE] Test::MockRandom 0.92"
    Date: Thu, 23 Dec 2004 06:49:28 -0600
    
    

    NAME
        Test::MockRandom - Replaces random number generation with non-random
        number generation

    SYNOPSIS
          # functional
          use Test::MockRandom;
          srand(0.5);
          if ( rand() == 0.5 ) { print "good guess!" };
      
          # object-oriented
          use Test::MockRandom ();
          my $nrng = Test::MockRandom->new(0.42);
          $nrng->rand(); # returns 0.42
      
          # override rand in another package
          use Test::MockRandom 'Some::Other::Package';
          use Some::Other::Package; # contains sub foo { return rand }
          srand(0.13);
          Some::Other::Package::foo; # returns 0.13
      
          # using a seed list and "oneish"
          srand(0.23, 0.34, oneish() );
          rand(); # returns 0.23
          rand(); # returns 0.34
          rand(); # returns a number just barely less than one
          rand(); # returns 0, as the seed array is empty
      
    DESCRIPTION
        This perhaps ridiculous-seeming module was created to test routines that
        manipulate random numbers by providing a known output from "rand". Given
        a list of seeds with "srand", it will return each in turn. After seeded
        random numbers are exhausted, it will always return 0. Seed numbers must
        be of a form that meets the expected output from "rand" as called with
        no arguments -- i.e. they must be between 0 (inclusive) and 1
        (exclusive). In order to facilitate generating and testing a nearly-one
        number, this module exports the function "oneish", which returns a
        number just fractionally less than one.

        Depending on how this module is called with "use", it will export "rand"
        either to the current package or to another specified package (e.g. a
        class being tested) or even globally. This module also includes the
        function "export_rand_to" which can be used to explictly override rand
        in another package after "use" has been called. See "USAGE" for details.

        Alternatively, this module can be used to generate objects, with each
        object maintaining its own distinct seed array.

    USAGE
      Overriding "rand" in the current package
        To override "rand" in the current package, simply "use" the module as
        normal.

         use Test::MockRandom;

        This imports "rand" and "srand" into the current namespace, masking any
        such calls from reaching the built-in functions. It also imports
        "oneish", and "export_rand_to".

      Overriding "rand" in a different package with "use"
        There are two ways to override "rand" in different package. The simplest
        is to provide the name(s) of the package to be overridden in the "use"
        statement. This will export "rand" to the listed packages and will
        export "srand", "oneish", and "export_rand_to" to the current package.
        You must "use" Test::MockRandom before you "use" the target package.
        This is a typical case for testing a module that uses random numbers:

         use Test::More;
         use Test::MockRandom qw( Some::Package );
         BEGIN { use_ok( Some::Package ) }
     
         srand(0.5)
         # assume sub foo { return rand } in Some::Package
         Some::Package::foo() # returns 0.5

        If you wish to export "rand" to both another package and the current
        package, simply include the current package in the list provided to
        "use". All of the following idioms work.

         use Test::MockRandom qw( main Some::Package );
         use Test::MockRandom __PACKAGE__, 'Some::Package';

         # The following doesn't interpolate __PACKAGE__ as above, but
         # Test::MockRandom will still DWIM and handle it correctly

         use Test::MockRandom qw( __PACKAGE__ Some::Package );
     
      Overriding "rand" in a different package explicitly with
    "export_rand_to"
        In order to override the built-in "rand" in another package,
        Test::MockRandom must export its own "rand" function before the target
        package is compiled. The simple approach (described above) of providing
        the target package in the "use Test::MockRandom" statement accomplishes
        this because "use" is equivalent to a "require" and "import" within a
        "BEGIN" block. To explicitly override "rand" in another package, you can
        also call "export_rand_to", but it must be enclosed in a "BEGIN" block
        of its own:

         use Test::MockRandom;
         BEGIN { Test::MockRandom::export_rand_to( 'AnotherPackage' ); }
         use AnotherPackage;
     
        This "BEGIN" block must not include a "use" statement for the package to
        be overridden, or perl will compile the package to be overridden before
        the "export_rand_to" function has a chance to execute and override the
        system "rand". This is very important in testing. The "export_rand_to"
        call must be in a separate "BEGIN" block from a "use_ok" test, which
        should be enclosed in a "BEGIN" block of its own:

         use Test::MockRandom;
         BEGIN { Test::MockRandom::export_rand_to( 'AnotherPackage' ); }
         BEGIN { use_ok( 'AnotherPackage' ); }

        Given these cautions, it's probably best to use the simple approach with
        "use", which does the right thing in most circumstances.

      Overriding "rand" globally
        This is just like overriding "rand" in a package, except that you
        override it in "CORE::GLOBAL".

         use Test::MockRandom 'CORE::GLOBAL';
     
         # or

         BEGIN { Test::MockRandom::export_rand_to('CORE::GLOBAL') }

        You can always access the real built-in "rand" by calling it explicitly
        as "CORE::rand".

      Overriding "rand" in a package that also contains a "rand" function
        This is tricky as the order in which the symbol table is manipulated
        will lead to very different results. This can be done safely (maybe) if
        the module uses the same rand syntax/prototype as the system call. In
        this case, you will need to do an explicit override (as above) but do it
        after importing the package. I.e.:

         use Test::MockRandom;
         use SomeRandPackage;
         BEGIN { Test::MockRandom::export_rand_to('SomeRandPackage');

        The first line is mostly to get the right exporting of auxilliary
        function to the current package. The second line will define a "sub
        rand" in "SomeRandPackage", overriding the results of the first line.
        The third line then re-overrides the "rand". You may see warnings about
        "rand" being redefined.

        Depending on how your "rand" is written and used, there is a good
        likelihood that this isn't going to do what you're expecting, no matter
        what. If your package that defines "rand" relies upon the system
        "CORE::GLOBAL::rand", then you may be best off overriding that instead.

    FUNCTIONS
      "new"
         $obj = new( LIST OF SEEDS );

        Returns a new Test::MockRandom object with the specified list of seeds.

      "srand"
         srand( LIST OF SEEDS );
         $obj->srand( LIST OF SEEDS);

        If called as a bare function call or package method, sets the seed list
        for bare/package calls to "rand". If called as an object method, sets
        the seed list for that object.

      "rand"
         $rv = rand();
         $rv = $obj->rand();
         $rv = rand(3);

        If called as a bare or package function, returns the next value from the
        package seed list. If called as an object method, returns the next value
        from the object seed list.

        If "rand" is called with a numeric argument, it follows the same
        behavior as the built-in function -- it multiplies the argument with the
        next value from the seed array (resulting in a random fractional value
        between 0 and the argument, just like the built-in). If the argument is
        0, undef, or non-numeric, it is treated as if the argument is 1.

        Using this with an argument in testing may be complicated, as limits in
        floating point precision mean that direct numeric comparisons are not
        reliable. E.g.

         srand(1/3);
         rand(3); # does this return 1.0 or .999999999 etc.

      "oneish"
         srand( oneish() );
         if ( rand() == oneish() ) { print "It's almost one." };

        A utility function to return a nearly-one value. Equal to ( 2^32 - 1 ) /
        2^32. Useful in "srand" and test functions.

      "export_rand_to"
         export_rand_to( 'Some::Other::Package' );

        This function exports "rand" into another package namespace. This is
        useful in testing object which call "rand". E.g.,

         package Some::Class;
         sub foo { print rand(); }

         package main;
         use Test::MockRandom;
         export_rand_to( 'Some::Class' );
         srand(0.5);
         Some::Class::foo(); # prints "0.5"
     
        Note that this uses the Test::MockRandom package globals, not class
        objects. So a call to "srand" in the main package still affects the
        results of "rand" called in "Some::Class".

        The effect of this function is highly dependent on when it is called in
        the compile cycle. See "USAGE" for important details and warnings.

    BUGS
        Please report bugs using the CPAN Request Tracker at

        http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-MockRandom

    AUTHOR
         David A. Golden (DAGOLDEN)
         dagolden@dagolden.com
     
         http://dagolden.com/

    COPYRIGHT
        Copyright (c) 2004 by David A. Golden

        This program is free software; you can redistribute it and/or modify it
        under the same terms as Perl itself.

        The full text of the license can be found in the LICENSE file included
        with this module.

    SEE ALSO
        Test::MockObject
        Test::MockModule


  • Next message: Terrence Brannon: "Re: [ANNOUNCE] Test::MockRandom 0.92"

    Relevant Pages

    • Re: Problem with "limited with" in a *real* application
      ... If you need overriding and/or dispatching somewhere, ... > package wx.Core.Sizer is ... I don't see any need for the conversions to Sizer_Type here. ... because you can't see inherited declarations. ...
      (comp.lang.ada)
    • "User-Defined Assignment" question
      ... Here's a package spec: ... package Pkg is ... end Finalize; ...
      (comp.lang.ada)
    • Re: overriding in private part
      ... Trying to find memory leak in AWS I found strange bug. ... There is a package hierarchy of three packages: ... A1.Base has primitive procedure P2 in private part of A1. ... That's one of the reasons "overriding" was added. ...
      (comp.lang.ada)
    • Re: Is method(super) legal?
      ... > Yes, you're right - that is the most common use, since overriding hides the ... package private by another package that is different from the ...
      (comp.lang.java.programmer)
    • KOMA script und mcaption tun nicht
      ... Alles soll in den Rand ... Package scrlfile, 2007/12/18 v2.98 KOMA-Script package ... mailto thomas j schrader at web de ...
      (de.comp.text.tex)