Saturday, December 3, 2016

Poor's man test notification

Somewhere 2014, my manager asked me to write down test cases for the application the team was developing. He didn't care the programming language I was going to use as long as I could implement it quickly.

Those tests should run regularly, and an e-mail should be sent in the event things go south.

Being used to write tests with TAP (Test::More), I went with Perl and Linux crontab for the job. Besides the tests itself (not really interesting for this post anyway), I end up with a generic script to run over the tests, analyze the results and send an e-mail with a nice HTML report attached. Here is the script:

use warnings;
use strict;
use TAP::Harness 3.30;
use TAP::Formatter::HTML 0.11;
use Email::Stuffer 0.009;
use Email::Sender::Transport::SMTP 1.300010;
use MIME::Base64 3.14;
use Authen::SASL 2.16;
use Config::Tiny 2.20;
use lib './lib';
my @tests = glob('Tests/*.t');


foreach my $test (@tests) {
   my $output_filename = 'results.html';
   my $fmt = TAP::Formatter::HTML->new();
   $fmt->output_file($output_filename);
   $fmt->verbosity(-2);
   my $harness = TAP::Harness->new(
       {
           formatter => $fmt,
           merge     => 1,
           lib       => ['lib']
       }
   );
   my $aggregator = $harness->runtests($test);


   if ( $aggregator->has_problems ) {
       send_email( $test, $output_filename );
   }
   else {
       remove_report($output_filename);
   }


}


sub remove_report {
   my $report_filename = shift;
   unlink $report_filename
     or warn "Could not remove unused report file $report_filename: $!";
}


sub send_email {
   my ($test_name, $attachment) = @_;
   my $cfg = Config::Tiny->read('xyz.ini');
   my $body = <<BLOCK;


Greetings,


Sadly a test ($test_name) executed against XYZ REST API failed.
Please check the attachment for details.


BLOCK


   my $transport = Email::Sender::Transport::SMTP->new(
       {
           host          => $cfg->{SMTP}->{'smtp.host'},
           ssl           => 1,
           sasl_username => $cfg->{SMTP}->{'smtp.username'},
           sasl_password => $cfg->{SMTP}->{'smtp.password'},
       }
   );


   Email::Stuffer->from( $cfg->{SMTP}->{'smtp.default.from.email'} )
     ->to('afreitas@foobar.com')->text_body($body)->transport($transport)
     ->subject('XYZ REST API failed')->attach_file($attachment)->send;
   remove_report($attachment);
}

Being generic enough, I could just point the script to different folders containing the tests and hopefully got nothing because all tests passed. In fact, it was so simple I wondered why something like this was not available on CPAN.

Well, not anymore... Test::Health is available for download already, so you can install it and run the script health_check.pl to run your tests. Since this script was created initially to health check the application, the name makes sense... but it seems to be generic enough to be reused in different situations that I didn't foresee when I wrote it.

The only thing that is missing from my original script is the SMTP authentication... hopefully I should implement subclasses to make it in the future (but contributions in that sense are welcome!).

Happy testing!


No comments:

Post a Comment