Blog post: Release 2.10 of Test::Timer

Jonas Brømsø - Feb 22 '19 - - Dev Community

I just made a release of Test::Timer and it should be available on local your CPAN now.

The release is a maintenance release, with some internal clean-up. But it I am particularly satisfied with the changes in this release, so I want to share the details with you.

Test::Timer provides a test interface adhering to the Test Anything Protocol (TAP) and integrating with the existing test tool-chain for Perl, it relies on Benchmark, which is a older, but stable and quite popular benchmarking module.

The default output from Benchmark looks as follows:

2 wallclock secs ( 0.00 usr +  0.00 sys =  0.00 CPU)
Enter fullscreen mode Exit fullscreen mode

This meant that earlier version of Test::Timer had to parse this string, in order to isolate data for use in the actual assertion part of the process.

Test::Timer hence implemented and nicely encapsulated this routine to do the parsing, using a regular-expression.

# helper method to change benchmmark's timestr to an integer
sub _timestring2time {
    my $timestring = shift;

    # $timestring:
    # 2 wallclock secs ( 0.00 usr +  0.00 sys =  0.00 CPU)
    my ($time) = $timestring =~ m/(\d+) /;

    return $time;
}
Enter fullscreen mode Exit fullscreen mode

Perl::Critic complained about the regular-expression not adhering to best practices for regular-expression.

This got me thinking. I love regular-expressions at the same time I know they can be error prone, hard to debug and in this case used for parsing output from a components beyond my control, meaning that the output could change without notice (meaning me not noticing). In this particular case I do not consider this a imminent risk, but still a risk.

Instead of spending time just adhering to the best practices for regular-expressions recommended by Perl::Critic, I decided to address the problem differently.

  1. The regular-expression changes would not address the parsing problem described above
  2. Benchmark had to offer more ways of excessing benchmark data or perhaps formatting the output

I read through the documentation and wrote up a small prototype.

First attempt was changes to the output format as offered by Benchmark, by altering the output from timestr. This did however prove not to be as simple as I would prefer and it would still require parsing.

Then I discovered the set of accessors and real seemed to be what I needed.

Here follows the final prototype:

#!/usr/bin/env perl

use strict;
use warnings;

use Benchmark;

my $t0 = Benchmark->new;

sleep(1);

my $t1 = Benchmark->new;

print timediff($t1, $t0)->real;

print "\n";

exit 0;
Enter fullscreen mode Exit fullscreen mode

And the final solution ended up looking as follows:

my $timestring = timediff( $t1, $t0 )->real;

return $timestring;
Enter fullscreen mode Exit fullscreen mode

From previously:

# parsing benchmark output
my $timestring = timestr( timediff( $t1, $t0 ) );
$time = _timestring2time($timestring);

return $time;
Enter fullscreen mode Exit fullscreen mode

I ended up factoring out _timestring2time and simply relying on Benchmark and learning some lessons:

  • Read all the documentation
  • Encapsulation is a savior

Next steps for following up on this is a complete encapsulation of the Benchmark object and evaluate using the "Dependency inversion principle".

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .