Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

ethan (3163)

  reversethis-{ed. ... rap.nov.olissat}

Being a 25-year old chap living in the western-most town of Germany. Stuying communication and information science and being a huge fan of XS-related things.

Journal of ethan (3163)

Sunday September 21, 2003
04:14 AM

Why I hate writing tests.

[ #14815 ]

They are by nature repetitive and tiring.

I'm done with all the XS and Perl code of String::Ruby and now need to test around 60 functions. Each test more or less has to be performed twice: for the functional interface and the autoboxed one. I decided to write one test-file for each function (resulting in around 60 .t files). I like each test-unit to be rather small, otherwise I quickly loose the orientation later.

The usual scheme is: input-string ==> apply function ==> output-string. For this module in particular, I need to always test special edge-cases. Those are: strings that contain 8-bit characters (should be left untouched for the moment) and strings containing the \0 character. Finally, one test tormenting the memory by feeding large strings.

It quickly dawned on me that

        is(Capitalize("hello"), "Hello");

is not an option here. So I eventually put the needed test-data in an array over which I can repeatedly iterate. Now a test-file looks pleasantly terse and tidy:

use constant TESTS => 31;
use Test::More tests => TESTS;
use Storable qw(dclone);

BEGIN { use_ok("String::Ruby", functions => qw(capitalize capitalizeI)) }

my @tests = (
        { str => "hello",
            res => "Hello",
            com => '' },
        { str => "HELLO",
            res => "Hello",
            com => '' },
        { str => "123ABC",
            res => "123abc",
            com => '' },
        { str => "ääääää",
            res => 'ääääää',
            com => "8-bit characters" },
        { str => "a" x 1_000_000,
            res => "A" . "a" x 999_999,
            com => "large string" },
        { str => "h\0Ello",
            res => "H\0ello",
            com => "embedded \\0 character" },

for (@tests) {
        is(Capitalize($_->{str}), $_->{res}, $_->{com});

for (my @cpy = @{ dclone(\@tests) }) {
        is(CapitalizeI($_->{str}), $_->{res}, $_->{com});
        is($_->{str}, $_->{res});

        skip "autobox not available", 12 if (! &String::Ruby::HAVE_AUTOBOX);
        use String::Ruby qw(no_croak);

        my @cpy = @{ dclone(\@tests) };

        for (0 .. $#cpy) {
                is($cpy[$_]->{str}->capitalize, $cpy[$_]->{res}, $cpy[$_]->{com});
                is($cpy[$_]->{str}, $tests[$_]->{str});

I scanned the oodle of Test:: modules on the CPAN whether one already offers such an infrastructure. Ideally, the above @tests array should be a simple object so that I can access the fields by method and not by hash-subscript (because I am lazy). Also, I wonder whether I can sensibly optimize away all those for-loops. They could become methods-to-be-overriden in my fictious Test-class which @tests would be blessed into. Resulting only in one call to $tests->run.

And we already have so many test-modules all trying to be ultra-smart so that we clearly need yet another one.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.