19 February 2012

QuickFIX buns

Writing applications with QuickFIX has some fun. The FIX engine there is a classical IoC, event driven. Application that uses it has to have only business specific things don't bother with tedious FIX noodles. Easy peeasy.

However, sometimes I have had anxiety because that specifics were not covered properly by tests. No, I tried, tried hard really. With mock or without it, tests for application with QuickFIX looks ugly and non readable due its restrictive and cumbersome design. Very often I had to remove them or simplify their verification because clearly understood that after couple months even I will not be able support it.

Eventually I came to an idea to simplify all that. QuickFIX users may appreciate this. :)

Each test has some expectations, for QuickFIX application tests it would be very useful to have an expected quickfix.Message instance. But not in form of whole FIX message that in natural form looks not so readable, it would be nice to focus on some certain fields which are important for this particular test. I tried to mock it, but got some cumbersome constructions instead. Here we come up with first hacks that suppose to simplify definition of expected message:

final Message message = new MessageMocker("W") {{
    imply("55=EUR/USD", "268=2");
    imply("269=1", "270=1.31", "271=1000");
    imply("269=2", "270=1.29", "271=1000");
}}.createMessage();

In additional, there is need specify a FIX message dictionary so you will work with message of proper protocol version. It can be done for whole test suite (class level) or for particular test (method):

@FIXDictionary(path = "FIX44.xml")
public class Test {

    @Test
    public void testFor44() throws InvalidMessage {
    }

    @FIXDictionary(path = "FIX42.xml")
    @Test
    public void testFor42() throws InvalidMessage {
    }
}

When expected message ready, we can check the tested code reaction on it. If there is something that changes state or in result of that message it is supposed to get an usual Java object in result, we can easily test it by wide variety of matchers. But if that is FIX message again, we are falling back into tedious spaghetti of verification code. Especially that is true of repeating groups that used very often. Even with mocking it looks cumbersome.

In attempt to simplify that and make test code more readable few matchers were provided. But let's look at example how they looks:

@Test
public void testExpectedFieldValue() throws Exception {
    final Message message = new MessageMocker("W") {{
        imply("55=EUR/USD", "268=2");
        imply("269=0", "270=1.31", "271=1000");
        imply("269=1", "270=1.29", "271=1000");
    }}.createMessage();

    assertThat(message, hasGroupThat(268, hasFieldThat(269, is("0"))));
    assertThat(message, hasGroupThat(268, 1, hasFieldThat(269, is("1"))));
}

The Market Data - Snapshot/Full Refresh (W) message here is created by already known message mocker as part of our testing stage. But it is only demo, in a real world it may be a real FIX message that may be generated as per a business case. In verification stage, this message is checked on presence specific fields. In our case, we going to check market data entry type (MDEntryType(269)) of 1st and 2nd repeating group respectively. Simple?

Sources could be found here, in a future I'll try to find out where it can be hosted for easier access from Maven.

No comments: