VeST Redux – Testing strategy for aggregates in DDD

A main part of VeST is the belief that, while unit testing at the class level can be useful, testing at the scenario level provides the same benefits with less cost of maintenance. How does that apply to root aggregates and CQRS?

Commands and events

If you’re working in a CQRS system, and most of us are, sometimes without realising it, then the world is split between things users want to do and things that happened. We call those commands and events.

The given/when split

One of my client, for better or worse, had spent years investing on an event-sourced infrastructure they did not need. The domain was too simple for it, but throwing everything away and arguing for a two weeks rewrite would have been irresponsible and disconnected from the realities of maintaining what was now a ball of mud.

A testing strategy was needed, to put the weeds under control and manage to make changes without everything breaking. We settled on a split between givens and whens.


Our aggregates were classes, with public methods on them, generating events which projected current state in internal private fields.

Commands were responsible for de-duping, ensuring idempotency, and calling those methods.

Event streams collected the various results of the method calls triggered by the commands.

Testing strategy

To keep the churn down as we evolved the system, we put in place the following rules.

Givens are only allowed to call methods on the aggregate. Then we wait for messages to propagate to any other part of the system, before going to the next when.

When’s are only allowed to execute commands. By executing the command from a known state, whatever changes may happen, the command is the main execution point that’s put under test.

Now how do we assert? Well, you cannot break encapsulation, so what do you do? We only test on projections.

Sum()’ing it up

So we run entity methods as givens, commands as when’s, and we test projections as then’s. If you can’t test your assertions through projections, then there is nothing to test.

That said, as event streams evolve over time, especially in poorly designed systems, things change and different rules apply. I shall cover this in a future post.


Rebuilding – Talks

I’ve been recovering from man-flu, and today is the first day where my brain has cleared enough to start coding again.

As I couldn’t focus on doing development, and I was bored in bed and running out of Netflix stuff to watch, I finally revamped the talks section of this site.

This has involved finding out about all the talks I gave since the first one, and each and every delivery of it since I started speaking in 2007.

You can now find descriptions, slides and videos for any of the 33 talks and workshops I’ve given, check any of the 89 times I’ve delivered them, marvel at the 36 cities and 12 countries I have covered.

The numbers were very fun to generate. How it’s done is pretty simple.

Each talk is part of a custom collection, as you’d expect, and I created a little YAML language that maps the information I found useful. This was already partly done in the old site, using one page per talk, but collections made it all easier.

The stats themselves, due to having poor support for maps, was calculated using arrays and nested loops, which reminded me of how we used to code in the 90s.

assign totalEvents = 0                                                      %}{%
assign cities = '' | split: ''                                              %}{%
assign countries = '' | split: ''                                           %}{%
assign all = site.talks | map: "deliveries"                                 %}{%
for deliveries in all                                                       %}{%
  assign totalEvents = totalEvents | plus: deliveries.size                  %}{%
  for delivery in deliveries                                                %}{%
    if delivery.location                                                    %}{%
      assign city = delivery.location | split: ',' | first | trim           %}{%
      assign country = delivery.location | split: ',' | last | trim         %}{%
      unless cities contains city                                           %}{%
        assign cities = cities | push: city                                 %}{%
      endunless                                                             %}{%
      unless countries contains country                                     %}{%
        assign countries = countries | push: country                        %}{%
      endunless                                                             %}{%
    endif                                                                   %}{%
  endfor                                                                    %}{%
endfor                                                                       %}

A few points of interest: first, the declarations at the top are the only way I know of initializing an array; second, the self-assignment with push is how i add things, because there is no uniq filter; and finally, the end-of-line kisses is the only way I can make the code readable and more maintainable. I call them kisses because it looks like two people kissing, isn’t that cute? And that’s thanks to the recently updated github pages, now with liquid 3.


Agile Anarchy – An introduction

One of the reasons I have been silent a lot in 2014 and 2015 is that I had the privilege of working with an amazing team. We created a completely new way of designing software, from the architecture to the organisation inside the team.

We found something special, and we started outreaching to the wider community to share our learnings. There is a lot in there, and that will result in yet another serial on this blog.

Rather than do an intro in text, you can start by watching the talk Marcin Floryan and myself gave at Lean Agile Scotland last year, which we called Your Agile is dead.

Sebastien Lambla & Marcin Floryan - Your Agile is Dead from Lean Agile Scotland on Vimeo.

Once you got that, you can listen to us discuss our approach to agile anarchy on the cucumber podcast.

Any feedback is more than welcome.