TDD – Have a Common Understanding in the Team

Recently I’ve been paying more attention to my style and approach to  TDD, and in doing so, I’ve begun to notice a few interesting things which, to me, seemed natural and almost “part of the process”, but clearly thats not the case with everyone. When I start on a dev task I typically try to ask as many of the right questions(see my previous post about avoiding autopilot) before I set off diving into code. I like to set the expectations of what it is that needs to be achieved, which is perfect in the world of TDD, because ultimately your tests should be testing the expectations match what actually happens.

I’ve come to learn that this isn’t necessarily the same “naturally assumed” approach which other developers might take. And along with that, there is mostly a misunderstanding within the team about what constitutes a focussed test, as well as what constitutes the definition of a category of tests. i.e. What qualifies as a unit test vs an integration test? And when to use them?

An experiment – collecting opinions

I thought I’d embark on a quick experiment and ask colleagues around me what their view on TDD is. Not surprisingly, there were a lot of different views and almost everyone I spoke to had a somewhat different idea of what TDD should be. Some advocating integration heavy tests to ensure business scenarios work, others advocate unit tests for quicker feedback etc. But what I found most interesting is that the definition of what a unit, integration, functional, end to end tests varied depending on who I spoke to! It became clear that is was common place to hear different vocabulary being used to describe the same end goal. For example I’d heard the terms “system testing”, “integration testing” and “acceptance testing” as well as “UAT” to all mean the same thing!

Clearing the  air

Obviously its fruitless to be embarking on a TDD journey if everyone int the team has a different idea of what its supposed to be. Most of the time when you hear the acronym “TDD” its automatically assumed to be unit tests that you’re writing, and for the large part, that might hold true. But I’m going to include other categories of testing that I feel should form part of the TDD paradigm. The definitions I supply below are not to be taken as solid regimented definitions, but more a way for teams to have a common understanding of what each area of TDD you’re targeting.

The Definitions

So lets clear the air a bit and define what is what. I’m obviously not the first person to write about the difference between unit and integration tests etc, but here’s what I find works:

Unit Test

A test that focuses on a single segment of behaviour. i.e. test that adding money to an account increases the overall balance. These tests should provide feedback as quickly as possible, and must run on every code change. And most importantly, a unit test is not something that touches 3rd party libraries/frameworks or resources which you have no control over. This includes interactions with a database, files system, and network comms as an example. Some might dispute that interactions between classes or modules that even you have written would be dumped in the integration category, but I disagree.

Integration Tests

Focussed on ensuring aspects of your code that interact with 3rd party libraries/frameworks and resources interact in the way you expect them to. i.e. writing an export file to disk, or saving an entity to the database successfully. These tests probably wouldn’t be run quite as often as your unit tests, as they could become quite heavy over time as the application grows. Typically, in most organisations I’ve worked in, these tend to run on every continuous integration build, and not necessarily on every code change – which included changes made while developing.

End to End/Acceptance Tests

Ensures that a business feature works as expected. This could include real world business scenarios from either through an API that has been built, or even through the UI – although this could be a whole other topic for another time. The point is, these end-to-end tests won’t run as frequently, and they will only test the core business scenarios. They involve complete vertical calls, and tend to be very CPU intensive, and are known to take large amounts of time to run. Especially as the application grows. Typically, you would have these run once a day, perhaps on a scheduled nightly build. If you happen to have introduced BDD into your development environment, these would be the tests I would expect to see running here.

So in summary, the real point here is that I was a little surprised that still to this day, many developers have a different take on what TDD is, and how to approach it, which might be fine, but in order for a team to produce good quality solutions and efficient code bases, then at the very least these teams all need to have a common understanding of what sort of tests they’re writing. Without it, your on a road, that will end in pain. Big pain.

AWS winning formula has to be Agile!

Recently I was at the Amazon Web Services summit, to try to sponge, yet again, as much information as I could. There’s no surprise that I left at the end of the day, not only exhausted, but with a notebook, full of my scribblings – both in the form of frantic notes, and the occasional stick man!

The last two summits I’ve attended here in London, have had increasing amounts of attendance, so I wasn’t too surprised to find that they had split up the day with different tracks for the different types of customer they had anticipated. Namely the newbie, who wants to know what AWS and the cloud is all about, then the advanced user, who’s been using it for a while and needs some tips and tricks, and then the “guided track” for those interested in Cloud Solutions.

For the most part, I found myself hopping between the novice and advanced tracks, trying to squeeze out the best I could from each session. However, I’m not going to describe all that I learnt there, because to be honest, a lot of what was covered there I’m pretty sure is material you could find on their website with a good enough search. No, what I am going to talk about it something that really struck me about AWS’s success.

It’s no secret, AWS are good at what they do, and they’re only getting better. What once started out as a modest attempt to offer services with names such as Elastic Compute Cloud (renting out computing capacity), Simple Storage Service (renting data storage) and Mechanical Turk (I didn’t know what that was either!), has now grown into what I think is a rather large, and ever-growing business. One of the reasons for their renowned success, hit me like a brick during a talk by Matt Woods – AWS are actually Agile!

Amazon have consistently displayed their uncanny ability to deliver small sets of features to their customers, allow for feedback, then iterate and improve. Rinse and repeat. This constant delivery of features – which by the way I think has been something like 6 new features a month on average – is what creates the buzz, and we as developers really love to try out new things. And as we do, we find some aspects which aren’t always to our liking, we tell AWS, and BINGO! they fix or enhance it. And in some cases I’ve heard from customers that they no sooner have given feedback, and the fix just happened to be released the next day!

AWS have been very focussed on customer feedback, and they take it very seriously. They listen, react, and in doing so, help strengthen their relationships with their customers. And I think they should be commended for adopting such a simple but effective strategy.

These very agile tenets of short cycles of delivery, frequent customer communication, and rapid response to what your customers regard as the most important focus, are what makes for delivering quality goods. In the case of AWS, it’s delivering a quality service, and in the case of software development, its delivering quality software.  So really they’re not very different. It just goes to show that, agile isn’t something that only has to be practised in a software development environment.