Posts Tagged ‘testing’

Mocking LWP::UserAgent with POST redirection

2010-04-11

To test the ubiquitous (and awesome) LWP::UserAgent module, I use Test::Mock::LWP. It works as advertised, with minimal code. However, I still found myself writing a little plumbing. Here are two code snippets that I use when using Test::Mock::LWP.

First, a way of mocking code using LWP::UserAgent’s requests_redirectable array, as in


sub _new_agent {
    my $agent = LWP::UserAgent->new;
    push @{$agent->requests_redirectable}, 'POST';
    return $agent;
} 

This won’t work with vanilla Test::Mock::LWP, as requests_redirectable is not a method and therefore cannot be mocked – a small flaw in UserAgent’s API. To circumvent the problem, mock your own UserAgent creation sub (you did encapsulate that, didn’t you):


use Test::MockObject;

# In addition to Test::Mock::LWP, we also need to mock our own
# wrapper for LWP::UserAgent->new, as it needs UserAgent's
# requests_redirectable array and the mock doesn't have that.
Test::MockObject->new()
  ->fake_module('My::Foo',
                '_new_agent' => sub { return LWP::UserAgent->new; }
               );

Second, just a tiny sub to make things nicer, IMHO: it provides a clean abstraction to get the latest requested URL. It’s useful if that’s all you want to test. This makes tests nicer to read and isolates them from the mocking module. It also encapsulates the magic index we need to get the requested URL from the request header array. The index is 2 here, this works for code making requests using HTTP::Request::Common. It’s probably different if you use HTTP::Request directly, but the test runner’s expected/actual output will quickly show you where the URL hides.

sub latest_requested_url {
    return scalar $Mock_request->new_args()->[2];
}
Advertisements

Testing Wicket ListViews using IVisitor

2009-11-05

The standard solution for unit testing Wicket apps is WicketTester. It works fine, but doesn’t offer much for testing ListViews. The assertListView method lets you test the contents of the ListView, but not the UI.

You can always extract the ListView rows into a Panel, of course. But when you don’t want to do that for whatever reason, it’s simple to side-step WicketTester and do the necessary tests yourself, especially since rows that are not in a panel of their own should be pretty simple.

An approach that works well for me is visiting the ListItems using MarkupContainer.visitChildren() and then accessing their components via Component.get(). To focus on the essential part, I’m using a method listView() in my example that gets the ListView from the rendered page. Once we have it, we visit its items.

listView().visitChildren(ListItem.class, new IVisitor<ListItem>()
{
	public Object component(ListItem item)
	{
		Component uri = item.get("uri");
		assertNotNull(uri);
		assertTrue(uri.getClass().isAssignableFrom(ExternalLink.class));
		
		// etc.
		
		// If testing one row is enough, we can stop here.
		return IVisitor.STOP_TRAVERSAL;
	}
});

Once you see it, it’s trivial. WicketTester’s assertComponent() isn’t magic, you can do the same in three lines: get the Component via its path, assert it’s actually present, and assert it’s the right type.

If you want to do further tests on the component’s internals, I find it practical to expose those through package-scoped methods, provided your tests are in the same package than your app.

Finally, something that bit me once: how ListItems work with the list model. Say we have this (just a rough sketch):

class Foo
{
	List bars;
	List<Bar> getBars() { return bars; }
}

// On some page, the model is a CompoundPropertyModel&lt;Foo&gt;.
add(new ListView<Bar>("bars")
{
	protected void populateItem(final ListItem<Bar> item)
	{
		item.add(new WebMarkupContainer("id"));
	}
});

If you get hold of the WebMarkupContainer(“id”), for instance using an IVisitor like I showed above, and you call getDefaultModelObject() on it, what do you get? One might expect a Bar; after all, it’s a ListView<Bar>. Not so – you get a Foo.

ListViews work on the original List instead of a copy. Each ListItem is backed by a ListItemModel, which knows the index of the element it represents, but has no model itself. When the model is looked up, the normal Wicket model chaining happens, so we get to the CompoundPropertyModel. The ListView code of course knows about this and uses the ListItemModel’s index to get the right Bar from the list. But getDefaultModelObject() doesn’t know about this and simply returns the Foo.

If you are in that situation, explicitly ask for the ListItemModel:

((ListItemModel) component.getDefaultModel()).getObject()

should give you a Bar. Of course, if you visit the ListItem itself like in the example above instead of a nested component, you can just call getObject() on it and it does the right thing.

Java-based JavaScript unit testing with Rhino

2009-10-28

At SwissProt, we test the UniProt website in several ways (though we still lack coverage, which is another topic). One area where testing was lacking for some time was JavaScript, which had accumulated over time to a somewhat substantial amount, about 3200 lines of code. We have Selenium tests for the site as a whole, but having unit tests for individual bits of JavaScript would have been great to make development of new code easier, and increase confidence in the code.

Many available frameworks such as JsUnit do in-browser testing. If you want to test actual UI code, that’s obviously what you need. But we have that at least partly covered with Selenium, and a problem with these tests is that they are difficult to run in an automated way, like from our ant test task. So I wanted something to easily and quickly test the UI-independent code, along with the Java code, from the command line, ant, or scripts. I also think that a standard JUnit-style test is way easier to write, but I guess that depends on what you’re used to.

Having read about Mozilla Rhino several times, a JavaScript interpreter written in Java with good integration between the two languages, I set out to see how much work it could be to write a simple test framework. As it turned out, it wasn’t much work at all, and there’s so little code that I can show all of it in this post.

(more…)

Mailtrap with JRuby

2009-07-02

Mailtrap, a mock SMTP server in a few lines of Ruby, doesn’t work with JRuby out of the box. One of its dependencies, the Daemons gem, uses fork which JRuby doesn’t implement as it’s not safe on the JVM:

$ mailtrap start
/work/software/jruby-1.2.0/lib/ruby/gems/1.8/gems/daemons-1.0.10/lib/daemons/daemonize.rb:103:in `safefork': fork is unsafe and disabled by default on JRuby (NotImplementedError)

My quick and dirty workaround was to simply ignore the daemon part and instantiate a non-forking instance of mailtrap running in the foreground:

$ jirb
irb(main):002:0> load 'PATH/TO/jruby/lib/ruby/gems/1.8/gems/mailtrap-0.2.1/lib/mailtrap.rb'
=> true
irb(main):003:0> Mailtrap.new('localhost', 5555, false, '/tmp/mailtrap.log')

You now have a Mailtrap running on port 5555, and see arriving messages right there in your IRB window. That should be enough for simple tests during development.