Monday, February 23, 2015

... about ugly UUID's in my tests



In my current project we use UUID's as id's for all aggregates. The good part of UUID's is that it's guaranteed to be unique. The ugly part is that it looks ... well ... ugly.

Writing tests with lots of UUID's clutters the test codebase and you lose focus on what it is you're testing.

A common use case when writing tests is that I want to assert that some id is the same as some expected id. For instance I want to test a filter - named VeryComplexFilter - that keeps users older than 40 and sorts them by age. The code is written in groovy:

Loading code....

I know. It's not the most compelling code, but lets continue for the sake of the example. My unit test creates a list of users and asserts the outcome of my filter. I'm using a data-driven test using spock because I want to test different inputs in the same test. Spock does a great job here.

Loading code....

In the where-block, I create the different input lists and define the expected  result. Each input list contains pairs of UUID-and-age tuples. In the when-block, each element of the input list is converted into a User object and handed to the filter under test. Finally in the then-block, the id's of the result list is compared against the expected results. When I run the test I get the following output:


You can see that the number of UUID's I have to create, really makes my test ugly. I could pregenerate them and then it would look like this:

Loading code....

It's the same test but I pregenerate the UUID's in a static list and refer to them from within the where-clause. However, what I really want, is to use some symbolic notation like a string that refers to a UUID. The test than would look much simpler:

Loading code....

In this where-block the input list contains a lists of strings like 'a-35' that I can refer to in the expectedResults. Now I can specify, for instance, that - provided with a list of users with ages 35, 52, 15, 79 and 41 - the filter must return the 2nd, the 5th and the 4th user. I do this by setting ...

  • the input list to "a-35", "c-52", "d-15", "e-79", "b-41" and 
  • the expectedResult to 'bce'
Every time I refer to uuid 'a' or 'b' or 'c', I want the system to remember what UUID I'm talking about. I can easily do that with the help of groovy's memoization:

Loading code....

I just call a closure named uuid that returns me the same UUID, every time I call it with the same input. Executing uuid.call('a') twice will always give me the same UUID. Executing uuid.call('b') gives me a new UUID.

What if I want to return something else instead of UUID's? I can do the same creating a user:

Loading code....

I can generalize this idea of creating something and return the same complex object, every time I call it with the same input parameter. Here's a method creating a complex object:

Loading code....

Here's how I call it and expect to get the same object for the same input value:

Loading code....

For this to work I need to be able to say: "This is how you create my complex object":

Loading code....

The above snippet registers a way to create the object and also passes the key that I can use to specify what I want. Once that's done, I can call it, like I did using the uuid closure call.

Loading code....

You can find a full gist here.

I don't know how far I'll take this trick in my tests. The fact that you can return the same - potentially complex - object and use some short symbol to reference it, helps a lot when trying to create some clear specification. However, there is some hocus-pocus going on, so it's not something I would apply everywhere... I think.

Greetings
Jan

Thursday, February 5, 2015

... about type safe closures in groovy

I've been using groovy for a couple of years now. I love it. It saved me from several nervous breakdowns coding in the pre-jdk8 world.

However, there's one thing that starts to annoy me.


It's closures. 
At least when passed as a parameter in a method, mimicking higher order functions.

In the following example, there's a CustomerNotifier that sends an email to a customer. It accepts a CustomerId and a closure creating the email. The closure is called with the Customer and a string indicating the environment ( we don't want to send emails to the real customers in a dev environment, do we):

Loading code....

In the method signature, there's no way to express what input parameters the closure needs. I can express the result, but not the input parameters.

That's annoying because now, the caller of that method, must look into the implementation to know what arguments will be passed to the closure. To make things worse, your IDE will not be able to assist you because it too won't have a clue of the parameters it expects. It's like typing blindfolded.

I could use @ClosureParams. This annotation provides extra information about the parameters a closure needs, assisting the IDE. However it just makes your code really ugly:

Loading code....

Lately I started using a library called functional java. It facilitates programming functionally in java and can be used by all poor souls that aren't allowed to program in scala but do want to use a more functional approach.

Among the basic stuff it contains interfaces for functions with 1 up till 8 input parameters. With these I can clearly define what input parameters my function needs.


Loading code....

Together with groovy's implicit closure coercion, I can use closures as typed functions while my IDE will resolve the input parameters for me and warn me when using the wrong type.

Loading code....

I'll definitely be using the functionalJava library more as it works great with groovy. There's also a groovy library building on top of functionalJava at https://github.com/mperry/functionalgroovy. It makes working with groovy even smoother but up till now I haven't really felt the need to use it.

You can find a gist of the complete example here.

Greetings
Jan