Sunday, January 21, 2007

JUnit-Style XML from Perl Test Files

Here is an experimental program that runs Perl test files and produces the same sort of XML output as the <junit> ant task.
Getting this XML output is helpful when running Perl tests under CruiseControl.

#!/usr/bin/perl

use strict;
use warnings;

use Test::Harness::Straps;
use Time::HiRes qw(gettimeofday tv_interval);
use XML::Generator ':noimport';

my @files = @ARGV;

my $strap = Test::Harness::Straps->new;
my $generator = XML::Generator->new(':pretty');

my @properties = _get_properties($generator);
my $test_results = _run_tests( $strap, $generator, @files );

my $xml = _get_junit_xml( $generator, \@properties, $test_results );

print "$xml\n";

exit;

#-------------------------------------------------------------------------------

sub _get_junit_xml {
my ( $generator, $properties, $test_results ) = @_;

my $system_out = 'system-out';
my $system_err = 'system-err';
my $xml = '';
$xml .= "\n";
$xml .= $generator->testsuite(
{
errors => 0,
failures => $test_results->{total_failures},
name => 'name of the test suite',
tests => $test_results->{total_tests},
'time' => $test_results->{total_time},
},
$generator->properties(@properties),
@{ $test_results->{test_cases} },
$generator->$system_out(),
$generator->$system_err(),

);
return $xml;
}

sub _run_tests {
my ( $strap, $generator, @files ) = @_;
my @test_cases = ();
my $total_tests = 0;
my $total_time = 0;
my $total_failures = 0;

foreach my $test_file (@files) {
my $start_time = [gettimeofday];
my $file_results = $strap->analyze_file($test_file);
my $elapsed_time = tv_interval( $start_time, [gettimeofday] );
$total_time += $elapsed_time;
foreach my $assertion ( @{ $file_results->details } ) {
if ( _skip($assertion) ) {
next;
}
$total_tests++;
$total_failures += _is_failure($assertion);
my $test_case = {
classname => $test_file,
name => $assertion->{name},
'time' => 0,
};
push @test_cases, $generator->testcase($test_case);
}
}
my $test_results = {
total_time => $total_time,
test_cases => \@test_cases,
total_tests => $total_tests,
total_failures => $total_failures,
};
return $test_results;
}

sub _skip {
my $assertion = shift;
return $assertion->{type} =~ / skip | todo /x;
}

sub _is_failure {
my $assertion = shift;
return !$assertion->{ok};
}

sub _get_properties {
my $generator = shift;
my @properties = ();
foreach my $key ( sort keys %ENV ) {
push @properties,
$generator->property( { name => "$key", value => $ENV{$key} } );
}
return @properties;
}

__END__

=head1 NAME

junit_xml.pl - Run Perl tests and get JUnit-style XML output

=head1 SYNOPSIS

junit_xml.pl file1 [ file2 ... ]

=head1 DESCRIPTION

Experimental script to run perl test files and produce the
same XML output as produced by the <junit> ant task.

=head1 DEPENDENCIES

Test::Harness
Time::HiRes
XML::Generator

=head1 BUGS

- Doesn't do anything with the STDERR from tests.
- Doesn't fill in the 'errors' attribute in the <testsuite> element.
- Doesn't handle when all tests in file are skipped (skip_all)
- Doesn't get the elapsed time for each 'test' (i.e. assertion.)


=head1 AUTHOR

Matisse Enzer <matisse@matisse.net>

=head1 COPYRIGHT & LICENSE

Copyright (c) 2007 Matisse Enzer. All Rights Reserved.

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

Technorati Tags: ,

Unix shell: Finding the run-time directory of a script

I've been trying to come up with an elegant way, in a shell script, to find the full path of the directory in which the script is located.

So far, I have this, which works for bash but not for sh (sh does not support substring expansion on variables):


 #!/usr/local/bin/bash -x
# Finds the full path to the directory containing this script

dir_containing_this_script=""
script_dirname=`dirname $0`
first_char="${script_dirname:0:1}" ; # Starting at index 0, 1 character
case "$first_char" in
("/")
# It's a full path. Use it unmodified.
dir_containing_this_script="${script_dirname}"
;;
(*)
# Strip leading . characters
while [ "${first_char}" = "." ]; do
script_dirname="${script_dirname:1}" ; # substring from index 1 to end
first_char="${script_dirname:0:1}"
done
current_dir=`pwd`
if [ -s "${script_dirname}" ] ; then
dir_containing_this_script="${current_dir}/${script_dirname}"
else
dir_containing_this_script="${current_dir}"
fi
;;
esac

echo "$dir_containing_this_script"


Update: Eric M on The WELL posted this most excellent solution:

dn=`dirname $0`
path=`(cd $dn; pwd)`
echo "path = $path"

Technorati Tags: , ,

Friday, January 19, 2007

Super Easy Graphics Programming

Eric Townsend pointed me to Processing - super easy programming environment for creating graphics programs.

Here's an applet I generated from it in a few minutes work, starting with an example Eric posted on The WELL.

/// start
void setup() {
size(600,600);
}

void draw(){
background(255);

int left_x = 0;
int right_x = width;
int top_y = 0;
int bottom_y = height;
int light_green = #99FF99;
int light_blue = #66CCFF;
int light_yellow = #FFCC66;
int pale_red = #FF3366;

for (int n=0; n < 100; n++) {
int y_of_n = n * (bottom_y/100);
int x_of_n = n * (right_x/100);

stroke(pale_red);
line(left_x,y_of_n,mouseX,mouseY);

stroke(light_yellow);
line(right_x,y_of_n,mouseX,mouseY);

stroke(light_blue);
line(x_of_n,0,mouseX,mouseY);

stroke(light_green);
line(x_of_n,bottom_y,mouseX,mouseY);
}
}

/// end

Technorati Tags: ,