Unit Tests In Perl

Prerequisite

In order to Unit Test our services with MOBY, we will be using the following Perl modules:

  • MOBY::Client::MobyUnitTest (perldoc)
  • MOBY::RDF::Parsers::ServiceParser (perldoc)

Additionally, you will need the location of a service’s description. In this tutorial, we will be using the RDF document that describes the service

Testing the Service

In order to test the service, we need to download and parse the RDF document into a MOBY::Client::ServiceInstance, using the

    MOBY::RDF::Parsers::ServiceParser


        # instantiate our ServiceParser with the
        # URL to our Service description
        my $parser =
                 MOBY::RDF::Parsers::ServiceParser->new();

        # parse the RDF document and get our service
        my $service_arrayref = $parser->getServices(
            "http://tinyurl.com/example-unit-test");

Once we have our MOBY::Client::ServiceInstance object, we can get all the unit tests for the object by calling unitTests(). In this case, there is only one MobyUnitTest, so we will take the first one

        # extract the first unit test
        my $unitTest = $service_arrayref->[0]->unitTests()->[0];

Now all that is left is to call the service using the example input (as specified by the service provider)

        # call the synchronous moby service
        my $service_output = doCall($service_name, $service_url, $service_input);

Once we have the output, we can then proceed to test the service.

We can compare the example output to the actual $service_output and get any semantic differences:

        # compare outputXML
        my $success = $unitTest->test_output_xml($service_output);
        print "Expected and actual output matched successfully!\n"
               if $success or $unitTest->expected_output eq "";
        print "There were differences found between the expected and actual output from the service!\n"
               unless $success  or $unitTest->expected_output eq "";

Or, we can apply the regular expression to our $service_output:

        # test against regular expression
        $success = $unitTest->test_regex($service_output);
        print "Regex matched successfully!\n"
             if $success or $unitTest->regex eq "";
        print "Regex didn't match!\n"
             unless  $success or $unitTest->regex eq "";

Or, we can apply the defined XPATH expression to our $service_output:

        # test against xpath expression
        $success = $unitTest->test_xpath($service_output);
        print "XPATH matched successfully!\n" if $success or $unitTest->xpath eq "";
        print "XPATH didn't match!\n" unless $success or $unitTest->xpath eq "";

That is all that there is to unit testing your services in Perl!

 

The full source code for this example:


#!/usr/bin/perl -w

use MOBY::Client::MobyUnitTest;
use MOBY::RDF::Parsers::ServiceParser;
use MOBY::Client::ServiceInstance;
use SOAP::Lite;

use strict;

# instantiate our ServiceInstanceParser with the URL to our
# Service description
my $parser = MOBY::RDF::Parsers::ServiceParser->new();

# parse the RDF document and get our service
my $service_arrayref =
  $parser->getServices("http://tinyurl.com/example-unit-test");

# extract the first unit test
my $unitTest = $service_arrayref->[0]->unitTests()->[0];

my $service_name  = $service_arrayref->[0]->name;
my $service_url   = $service_arrayref->[0]->URL;
my $service_input = $unitTest->example_input;

print "Here is the unit test that we have:\n\n"
  . "\tExample input:\n$service_input\n\n"
  ."\tExpected output:\n"
  . (
	    $unitTest->expected_output eq "" ? "\t\tnone provided."
	  : $unitTest->expected_output
  )
  . "\n\n"
  . "\tXPATH:\n"
  . (
	    $unitTest->xpath eq "" ? "\t\tnone provided."
	  : $unitTest->xpath
  )
  . "\n\n"
  . "\tREGEX:\n"
  . (
	    $unitTest->regex eq "" ? "\t\tnone provided."
	  : $unitTest->regex
  ) . "\n\n\n";

# call the synchronous moby service
my $service_output = doCall( $service_name, $service_url, $service_input );

# compare outputXML
my $success = $unitTest->test_output_xml($service_output);
print "Expected and actual output matched successfully!\n"
  if $success
	  or $unitTest->expected_output eq "";
print
"There were differences found between the expected and actual output from the service!\n"
  unless $success
	  or $unitTest->expected_output eq "";

# test against regular expression
$success = $unitTest->test_regex($service_output);
print "Regex matched successfully!\n" if $success or $unitTest->regex eq "";
print "Regex didn't match!\n" unless $success or $unitTest->regex eq "";

# test against xpath expression
$success = $unitTest->test_xpath($service_output);
print "XPATH matched successfully!\n" if $success or $unitTest->xpath eq "";
print "XPATH didn't match!\n" unless $success or $unitTest->xpath eq "";

sub doCall {
	my ( $name, $url, $input ) = @_;
	my $out;

	my $soap =
	  SOAP::Lite->uri("http://biomoby.org/")->proxy( $url, timeout => 20 )
	  ->on_fault(
		sub {
			my $soap = shift;
			my $res  = shift;

			my $msg =
			  ref $res
			  ? "--- SOAP FAULT ---\n"
			  . $res->faultcode . " "
			  . $res->faultstring
			  . "--- SOAP FAULT ---\n"
			  : "--- TRANSPORT ERROR ---\n"
			  . $soap->transport->status
			  . "\n$res\n"
			  . "--- TRANSPORT ERROR ---\n";

			die $msg;
		}
	  );
       # call the soap service
	$out = $soap->$name( SOAP::Data->type( "string" => "$input" ) )->result;

       # return the output
	return $out;
}