The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Test::Sims - Helps build semi-random data for testing

SYNOPSIS

package My::Sims;

use Test::Sims;

# Creates rand_name() and exported on demand.
make_rand name => [
    qw(Mal Zoe Jayne Kaylee Inara River Simon Wash Zoe Book)
];

# Automatically exported
sub sim_character {
    my %defaults = (
        name   => rand_name(),
        series => "Firefly",
    );

    require Character;
    return Character->new(
        %defaults, @_;
    );
}

DESCRIPTION

THIS IS AN EARLY RELEASE! While very well tested behaviors may change. The interface is not stable.

This is a module to help building semi-random data for testing and to create large, nested, interesting data structures.

This module contains no new assertions, but it does tie in with Test::Builder.

It does two things. It contains functions which make generating random data easier and it allows you to write repeatable, yet random, test data.

make_rand()

my $code = make_rand $name => \@list;
my $code = make_rand $name => sub { ... };

Creates a subroutine called <rand_$name> and exports it on request.

If a @list is given it will generate a subroutine which returns elements out of @list at random. It takes min and max arguments to control how many.

my @items = rand_$name(
    min => $min_random_items,
    max => $max_random_items
);

min and max both default to 1. So by default you get 1 item.

If a subroutine is given it will simply give that routine a name. This is just to get the convenience of adding it to the exports.

Also adds it to a "rand" export tag.

{
    package Sim::Firefly;

    make_rand crew => [
        qw(Zoe Wash Mal River Simon Book Jayne Kaylee Inara)
    ];
}

...later...

{
    use Sim::Firefly ":rand";

    my $crew = rand_crew;             # 1 name
    my @crew = rand_crew( max => 3 ); # 1, 2 or 3 names
}

export_sims()

export_sims();

A utility function which causes your module to export all the functions called <sims_*>. It also creates an export tag called "sims".

You should call this at the end of your Sim package.

Controlling randomness

You can control the random seed used by Test::Sims by setting the TEST_SIMS_SEED environment variable. This is handy to make test runs repeatable.

TEST_SIMS_SEED=12345 perl -Ilib t/some_test.t

Test::Sims will output the seed used at the end of each test run. If the test failed it will be visible to the user, otherwise it will be a TAP comment and only visible if the test is run verbosely.

If having new data every run is too chaotic for you, you can set TEST_SIMS_SEED to something which will remain fixed during a development session. Perhaps the PID of your shell or your uid or the date (20090704, for example).

sim functions

Test::Sims doesn't do anything with functions named sim_* but export them. Generally we recommend they're written like so:

sub sim_thing {
    my %defaults = (
        name        => rand_name(),
        age         => rand_age(),
        motto       => rand_text(),
        picture     => rand_image(),
    );

    return Thing->new( %defaults, @_ );
}

This way you can get a completely random Thing.

my $thing = sim_thing();

Or you can lock down the bits you need leaving the rest to float free.

# Joe's motto and picture remain random
my $joe = sim_thing(
    name => "Joe",
    age  => 64
);

EXAMPLE

Here's an example of making a simple package to generate random dates.

package Sim::Date;

use strict;
use warnings;

require DateTime;
use Test::Sims;

make_rand year  => [1800..2100];

sub sim_datetime {
    my %args = @_;

    my $year = $args{year} || rand_year();
    my $date = DateTime->new( year => $year );

    my $days_in_year = $date->is_leap_year ? 366 : 365;
    my $secs = rand( $days_in_year * 24 * 60 * 60 );
    $date->add( seconds => $secs );

    $date->set( %args );

    return $date;
}

export_sims();

And then using it.

use Sim::Date;

# Random date.
my $date = sim_datetime;

# Random date in July 2009
my $date = sim_datetime(
    year  => 2009,
    month => 7,
);

ENVIRONMENT

TEST_SIMS_SEED

If defined its value will be used to make tests repeatable. See "Controlling randomness".

SEE ALSO

"Generating Test Data with The Sims" http://schwern.org/talks/Generating%20Test%20Data%20With%20The%20Sims.pdf is a set of slides outlining the Sims testing technique which this module is supporting.

Data::Random for common rand_* routines.

Data::Generate to generate random data from a set of rules.

SOURCE

The source code repository can be found at http://github.com/schwern/Test-Sims.

The latest release can be found at http://search.cpan.org/dist/Test-Sims.

BUGS

Please report bugs, problems, rough corners, feedback and suggestions to http://github.com/schwern/Test-Sims/issues.

Report early, report often.

THANKS

Thanks go to the folks at Blackstar and Grant Street Group for helping to develop this technique.

LICENSE and COPYRIGHT

Copyright 2009 Michael G Schwern >schwern@pobox.com<

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

See http://www.perl.com/perl/misc/Artistic.html