Wednesday, January 28, 2009

Exobrain Note: Benchmark CGIs under Apache::Registry and without

Exobrain Note

Need to benchmark some of our internal CGIs under Apache::Registry and without to see what the performance gain might be.

I think building a client for the apps with WWW::Mechanize and WWW::Mechanize::Timed would be enough to evaluate the change.

Tuesday, January 27, 2009

SOAP::Lite and Test::MockModule

Intro

As part of a project to convert an existing SOAP client library over to a new version of calls, I found that I needed a way to test potential faults and new data formats without requiring live calls. After I built it for the new stuff, I used it to test existing calls and errors as well. This code was running live for several years before I needed to change it for the new version, this inspired me to be very careful and invest in testing. On a side note, I found plenty of bugs just creating the test suite in the existing code that had been there for years.

Creating the Test Suite

To create the test suite, I needed to pretend to get SOAP server responses. I turned to Test::MockModule to step in and provide hooks to return them. I found that mocking these responses were pretty straightforward once I figured out how to use the SOAP::Lite deserializer. (like most things, its easy once you know how)

The following outlines what I did to create the suite, well at least the process of using MockModule to mock the responses.

Overall, there are three high level steps:
  • Capturing or constructing the SOAP XML responses
  • Locating SOAP::Lite calls in our client library that dispatch requests
  • Constructing needed Mocked SOAP::Lite methods
The first two parts are pretty specific to your own environment and code base. I was able to grab faults from the service by making bad calls to the old and new version. For a response, I had an example of the new response from the web service owners. Since backwards compatibility was important in my case, I grabbed many existing calls responses.

Our code made requests by passing a XML document (that was the request) to the SOAP::Lite call method. Its a bit of an unusually approach to use with SOAP::Lite. I think a little exploration into using MockModule with the autodispatched method might be interesting, another day. This post will show how to mock responses returned from the call method.

Mocking it

Test::MockModule requires you to first declare the module that you want to mock. In my case, we used SOAP::Lite as composite in a class instead of sub class.

First, I had MockModule pretend to be a SOAP::Lite object.
  my $lite = Test::MockModule->new('SOAP::Lite');
Next I created my object that contained a SOAP::Lite object:
  $soap = Our::Client::SOAP->new( %params );
Then I setup the mocking of the call method. Since my later test calls need to use the data returned from the method, I need to mock the a response with real data returned. In the snippet below, get_good_response returns a XML document. Using the SOAP::Lite deserializer ensures that I test the parsing of the response by SOAP::Lite (instead of returning the expected data structure).
  ## fake out call with error response
$lite->mock(
call => sub { return SOAP::Deserializer->deserialize( get_good_response() ); }
);
Next I run our client's method that uses the call. In this case the interface is not really the best but try to look beyond that.
  ( $ret, $res ) = $soap->process;
Lastly I check the data $ret and $res for data. In my case $ret returns -1 on error (please in your own libraries throw faults instead of strange return codes).
  is $ret, -1, "process ret";
is $res->dataof('//BirthDay'), '2009-01-15', 'BirthDay Result';
That is it. Of course I had many mock calls to simulate the server not responding and various faults.

Here a complete example:
use Test::More qw( no_plan );
use Test::MockModule;
use Test::Exception;
use Carp; ## for faking out soap::lite
use File::Slurp qw( slurp );

BEGIN { use_ok 'Our::Client::SOAP'; }

{
my $soap;
my ($res, $ret);
my $lite = Test::MockModule->new('SOAP::Lite');

lives_ok { $soap = Our::Client::SOAP->new( %params ); } 'Constructor';

$lite->mock(
call => sub { return SOAP::Deserializer->deserialize(get_fault_resp_ver1()); }
);

lives_ok { ( $ret, $res ) = $soap->process } 'process - fault';

cmp_ok $ret, '==', -1, "process ret";
ok $res->fault, "fault exists";
}

sub get_fault_resp_ver1 { return scalar slurp q{fault_version_1.xml} }
The End... for now

Tuesday, January 20, 2009

vim makes me pasty when pasting

For a while its bugged me that when I paste into a vim session with all nice options turned on, it formats the crap out of it. At some point setting set noautoindent stopped fixing this problem.

Thank goodness that I found a solution, it probably exists for years but with vim sometimes knowing the right verbage is the key to a finding how to do it. (its probably been there since version 5.0)

Here is how it works for me:
  1. pre paste - :set paste
  2. paste in code/snippet/sql/guinea pig
  3. :set nopaste
Man that makes my life so much easier...

Sunday, January 11, 2009

Switch between windows in any application on OS X

To switch between windows in any application on OS X use: cmd - `.

I started to think this was only in Safari but it works with any multi-window OS X app.

Sweet!

Friday, January 9, 2009

A new must use module - Test::Exception

I write quite a few unit tests that have methods or subs that throw exceptions (like most good code should... this rule has numerous good exceptions! hahaha, sorry couldn't resist.). A few months ago I ran across Test::Exception.

In the past I would often write unit tests for these cases like:
{
my $err;
my $obj;

eval { $obj = MyObject->new; };

## constructor expected to fail
$err = $@;
ok $err, "constructor - missing parameters";

## or for methods that aren't suppose to throw
eval { $obj = MyObject->new( server => 'localhost' ) };

## check constructor
$err = $@;
ok !$err, "constructor";
isa_ok $obj, 'MyObject';
}
This construct became very tiring, verbose and distracts from what is really going on. (Yuck!)

With Test::Exception, I can convert these annoying eval blocks into nicely contain lines.

Example from above:
use Test::Exception;

{
my $obj;

throws_ok { $obj = MyObject->new; } qr/Error Message to match/,
'constructor - missing parameters';

lives_ok { $obj = MyObject->new( server => 'localhost' ) } "constructor";
isa_ok $obj, 'MyObject';
}
The only thing that is a bit of a syntax gotcha is that the lives_ok requires a parameters of 'block "string"'. Notice that missing comma, odd but it is much better than my previous eval crap.

Test::Exception really makes this better, thanks to the author.

Tuesday, January 6, 2009

Vim, Tidy and XML - how to make them work together

Background

I use vim as my main IDE. I found that I often have to muck and view XML. Often this XML is from debugging logs or output that don't add whitespace (and why would they).

The following is my setup for a small vim filetype mapping to automatically clean up xml using HTML tidy. Another great tool.

How To

First, You'll need $HOME/.vim and $HOME/.vim/ftplugin directories.

Create them, if they don't exist:
  mkdir -p $HOME/.vim/ftplugin
Second, create a new ftplugin for xml.
   vim $HOME/.vim/ftplugin/xml.vim
Third, add mapping for tidy (I use F3)
" tidy for xml -q makes it quiet
map <F3> :%! tidy -q -i -xml % <CR>
Now when you edit a file with a type of xml, you can press F3 your xml will be tidy'd. This does require that you save the xml file somewhere first (you'll need a valid filename).

Caveats

  • I've only used this on UN*Xs OSs
  • I use vim 7.x, it will probably work on 6
  • I enable filetype support in my .vimrc with command filetype plugin indent on
  • On solaris I have to do some crazy function key mapping inside of .vimrc
End transmission :)