A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Jump to

Quick reference

XML::Validator::Schema

#!/usr/bin/perl

use XML::SAX::ParserFactory;
use XML::Validator::Schema;
# create a new validator object, using foo.xsd
$validator = XML::Validator::Schema->new(file => 'foo.xsd');
# create a SAX parser and assign the validator as a Handler
$parser = XML::SAX::ParserFactory->parser(Handler => $validator);
# validate foo.xml against foo.xsd
eval { $parser->parse_uri('foo.xml') };
die "File failed validation: $@" if $@;

The problem is:

Validating with XML::XPath

use XML::XPath; # update: use XML::LibXML and XML::LibXML::XPathContext instead
use Test::More qw(no_plan);

my $id = 298;
my $xml = &get_url("/$id")->{xml};
my $xp = XML::XPath->new( xml => $xml );
my $r = '/feed'; # root
ok( $xp->exists($r), "there should be a feed" );
ok( $xp->exists("$r/id"), "there should be a feed ID" );
ok( $xp->find("$r/id") =~ m{/$id}, "feed ID should be correct" );
ok( $xp->exists("$r/link[\@rel=\"self\"]"), "rel=self attr is correct" );
ok( ($xp->find("$r/link")->get_nodelist)[0]->getAttribute('href'), "href link exists" ); # this is ugly
check( $xp->find("$r/updated") => like => qr/^\d{4}\-\d\d\-\d\dT\d\d:\d\d:\d\d\.\d+Z$/ );

my $entries = $xp->find("/feed/entry"); # find all entry sections
ok( $entries, "there are entries" );
if ($entries->size) {
my $e = "/entry";
foreach my $node ($entries->get_nodelist) {
# it's bloody stupid transforming the XML::XPath object to a string and then parsing back to an object
# instead maybe loop through each node in the list using xpath [0] [1], etc?
# But why should I have to hack around this....
my $entry = XML::XPath->new( xml => $node->toString );
ok( $entry->exists("$e/title"), "title exists" );
}
}

# Conclusion: XML::XPath is bad for writing tests.

Crontab format (V3)

MAILTO=me@there.co.uk

# minute (0-59),
# | hour (0-23),
# | | day of the month (1-31),
# | | | month of the year (1-12),
# | | | | day of the week (0-6 with 0=Sunday).
# | | | | | commands
# 3 2,3,4 * * 0,6 /command to run on more than one day/hour
# 3 2,4-7 * * 1-5 /another/command to run on a range of days/hours

04 10 * * * /command/here 2>> /path/to/log/prog.$(date +\%Y\%m\%d).log

NOTES:
  • You must escape percent signs with a backslash
  • Putting them in double quotes doesn't work
  • Putting in double quotes and backslashes works, but the backslashes are written as part of the filename. So don't so that.

Perl test template

Comments: Logging may be mostly useful for debugging -- the log level can be raised for release.

#!/usr/bin/perl

#################################################################################
# Description of tests
#################################################################################

use strict;
use warnings;

use Test::More qw(no_plan);
use Test::Differences; # eq_or_diff()
use Test::Lazy qw/try check/; # check() displays the expected & actual upon failure, even for scalars
use Log::Log4perl;
use XML::Simple qw(:strict);

Log::Log4perl::init('conf/log4perl-test.conf');
my $LOG = Log::Log4perl->get_logger('log4perl.appender.LOGFILE');

$| = 1; select STDERR;
$| = 1; select STDOUT;

$LOG->info("Started tests");

use_ok('MyNamespace::MyModule');

dies_ok { MyNamespace::MyModule->new } 'fail to instantiate without parameters';

my $m = MyNamespace::MyModule->new( url => "foo", name => 'bar');
isa_ok($m, 'MyNamespace::MyModule');