I Don’t Write Unit Tests Because…. : The Excuses

As someone who’s seen the benefits of the approach, I’m a huge believer in test driven development. It adds a level of quality and maturity to the field of software development, yet it’s still not a widespread practice across development projects. When it comes to a choice between the features, time and quality, it’s always the quality that suffers. We don’t want to add extra time for testing and we don’t want to compromise on the feature set of the delivery. If you haven’t set out to do test driven development at the start of the phase, then it’s difficult to fit in.

We’ve all heard excuses for not taking the test driven approach, but nowhere compiles them better than “Pragmatic Unit Testing in Java With JUnit“, from the Pragmatic Bookshelf.  I read the book a few years ago, and afterward I thought there was no way that any responsible developer could read the book without truly believing that unit tests were one of the most important aspects of the development activity.

The most worrying excuse I’ve heard is that it’s too difficult to test my code. This can be for one of two reasons. One is that your code is mainly UI related, and automating the UI tests is too difficult. I’ll concede that UI automation is a tricky area (but not impossible, as we’ll see in a later article), but every effort should be made to automate it if possible: think about regression tests. If you have a fully automated test suite, including the UI behaviour, you can make a change to your code, and have full confidence that you haven’t broken anything if you have tests to re-run.

The second reason that your code is too difficult to test is that you’ve messed up your design. Maybe your logic and UI code are too tightly coupled, and without that automated UI layer existing, the dependency between the logic and the UI will cause a problem. This is where test driven development helps to ensure a clean design, following best practices. Using JUnit is simple, so if I can just point my test at a clean logic layer, I can test all logic that the UI will ever touch.  What’s that? You’re missing your data model? Well then just use mock objects – there are many frameworks for that!

For those who haven’t read the book yet, I’ll give a quick summary of the excuses for not testing as outlined in the introduction chapter:

  • It takes too much time to write tests
    As the number one reason that developers give, and thinking back on my own education, I think this is down to the way computer science is taught. For the most part, we’re lead to believe that testing happens at the end of the process, not all the way through. 

    Pragmatic Unit Testing encourage the “pay as you go” model, where having tests written as you are developing means that you don’t have that crunch time at the end where you try to cram all your unit tests in.

    Anyway, if you’re not writing tests as you go along, how are you checking if the code behaves as you expect? You run it manually? Wouldn’t it make sense to invest some of that manual testing time into writing a JUnit test for it? I mean you’ll have to run that piece of code again sometime – it’s not going to remain untouched for the lifetime of the product.

    In fact, there are many more time penalties that happen if you don’t write unit tests. You’ll have to spend time debugging code trying to work out why something doesn’t work. Or you’ll refactor the code, and then find that nothing works as it used to after the refactor. If you had the unit tests written, you have a base of confidence.

  • It takes too long to run the tests
    I’ll admit, there can be a good amount of time taken running tests that involve external entities, or the user interface. But you’re supposed to have more than one level of test. The unit level tests should run quickly, and there may be a level of integration tests that can run without a big time impact. If there are higher level integration tests that are taking time, just run them less frequently – maybe even in a nightly build. That’s not to say you should ignore the lower level unit tests. These should always run fast enough that it becomes a natural part of your own development process.
  • It’s not my job to test code
    I don’t know at what stage a software developer decides that he can just throw code over the wall. If your job title was simple Coder than maybe there’s an excuse. But as your job is to develop working software, you need to be able to say that your code is functional.  The book makes a good point that if the QA development finds it difficult to find bugs in your code, it will do wonders for your reputation.
  • I don’t really know how the code is supposed to behave so I can’t test it
    This is a difficult one to react to without incredulity. If you don’t know how the code is supposed to behave, you shouldn’t have started writing it. You need to understand the requirements first.

There are a few more excuses listed in the book, but these are the main ones. What are the excuses that you’ve heard for not writing tests.

Write Your Good Code First

Writing good code first is a pretty obvious statement, but I’m not sure if people do this. In fact, I think that we make excuses all the time so that we don’t have to.

While catching up on Twitter recently, I checked what@UncleBob (Robert Martin, author of Clean Code) has been saying. Obviously he’s a smart guy, as pragamatic as they get, and always has useful insightful things to say. Here’s the tweet that caught my attention:

I’m sure most developers would say that they write good code, always. Think about it? Do you? I know I’ve definitely compromised my quality standards in the past, deciding that it’s better to “fix that later” rather than to get it right first time. The minute you do that, you’ve broken a window.

While on this topic of writing good code first, you might wonder where refactoring fits (but I hope that you’re not wondering!). Refactoring is inevitable, but what really gets me is when refactoring needs to be put down as a separate task in a project schedule. Looks like UncleBob would agree:

So why does it happen?  To me, seeing refactoring in the schedule is an admission that “you’re not going to get it right first time, so we’ll add in this extra time to fix it later”. Surely if there is a concern that the time allocated to a task doesn’t cover a complete, clean implementation, the task needs more time. Refactoring is a good thing, but you have to refactor as you go. Don’t commit too much code littered with //TODO comments, do it now.

Having refactor seen as a different task is the same as breaking down each feature into a list of tasks like design, unit test, code, refactor, test. Software developers should know what they need to do in order to produce quality software. The “task” is not just the coding part – it’s everything around it.



Creating Better Presentations

Creating presentations is a skill that is often overlooked by software developers, but it can be one of the most important parts of a developers toolbox. Getting a clear message across to your colleagues or management is vital. Of course, if you plan on presenting at a conference, writing a good presentation is even more important. The following set of slides from @jessedee, give a great set of tips to presenters:

View more presentations from @JESSEDEE

One of the tips highlighted here is that Powerpoint, or at least the templates that you get from Powerpoint, forces your presentation into a boring format. It’s something that we’ve all seen – too many bullet points and too much text. This leads to the audience doing more reading than listening. When it gets to this stage, you wonder why not just send around a document.

Another great resource for aspiring presenters is Presentation Zen. Steve Jobs is always quoted as an example of a great presenter.

Everything mentioned so far is fine more marketting or high level presentations. A lot of developers think that a technical presentation can’t conform to the above rules. But why not? You should still get the point across with an impressive visual presentation – the idea is to inspire people, or to convince them that you know what you’re talking about. Supporting documentation can be provided to the audience after the presentation.

What tips have you got for creating brilliant presentations? Are there any examples you’d like to share to highlight the very good (and the very bad!).

Creating An Agile Culture

I’d like to get rid of the illusion that your software development process determines if your company is ‘agile’ or not. It’s down to the culture, the mindset.

To prove this, we have to go back in time a bit – to February 2001 actually – where the Agile Manifesto was set down. It’s amazing how many people read this, and don’t pay attention to what’s said. To summarise:

  • Individuals and interactions over processes and tools
  • Working software over comprehensive documentation
  • Customer collaboration over contract negotiation
  • Responding to change over following a plan

So, point number one, says that’s it’s about the people in your team and not the process you’re using. I’ve even heard people go as far to say that you can still be agile using a Waterfall process – after thinking about it, I don’t disagree.

So, the key thing, is responsive, responsible individuals on your team who are focussed on the project outcome.
To get the whole thing right, there’s a few values that need to be maintained. Here’s my list of what those things are:

  1. Communicate
    The standing meetings concept (mostly from XP) is a good one. Don’t worry about having a meeting for the sake of it – invariably, someone will have something to say – and if there’s nothing important, the meeting will be over quickly anyway.
    Make sure that all team members give updates on what they are doing. Something you think isn’t important might be vital for someone else to know.
    Keep the test team involved (there’s a tendancy for developers to leave them out) and make sure to leverage their experience.
    Encourage desk reviews of code and design with all the stakeholders.
    Everyone should try and inject energy into the team – if everyone feels empowered, encouraged and motivated, you’ll have no problems reaching the project goals.
  2. Blame Doesn’t Fix Bugs
    Solution oriented people are much more useful than problem oriented. That’s a known fact – and it holds true in software development too. Casting blame makes people feel defensive, while being constructive makes people feel empowered. The focus needs to be on outcomes, and the team should work together to find ways to solve problems, rather that over analysising them.
  3. Fix Misunderstandings
    This could fall under the communications category, but I thought it’d be good to add in as a seperate issue. Consider, if someone misunderstands a requirement, API call or a decision, chances are someone else has also misunderstood. So, when you’re addressing one persons misunderstanding, make sure everyone else knows about the clarification too.
  4. Keep It Simple
    Ask yourself if what you’re about to do is required for the project outcome. You’ll be surprised how many times it isn’t. Don’t write documents unless you really have to.
    A simple design always takes less time to finish than a complex one, and is a lot easier for everyone in the team to understand.
    Keep things as simple as possible for as long as possible by never adding functionality before it is scheduled.
    I looked at a Standish Software Survey graph – it showed that there was 45% of features that are never used. NEVER! So I definitely don’t want to spend my time working on Never Used stuff.
    That alone is motivation for me to make sure what I work on is relevant.
  5. No Broken Windows
    Anyone that’s read The Pragmatic Programmer will be familiar with this.
    The experiment carried out goes along the lines of leaving a nice car in a dodgy neighbourhood. They come back a week later, it’s still there in perfect condition.
    So they break a window, come back the next week and the car is burnt out.
    Why? Because they started a pattern of disrespect.It’s the same in software – no one wants to be the first to start this pattern – I don’t want to be first to introduce a defect. So if we repair any “broken windows” as soon as they appear, everything will be in prestine condition for the duration of the project.
    This really is worth noting – maintain high standards in everything that you do.
  6. Embrace Change
    Decisions – in software they’re not cast in stone, they’re written in sand. Things will change, and there’s no point complaining. If something does change it’s for the good of the project outcome.
    Embrace change (as XP would recommend), or just roll with it.
    Don’t fixate on a given plan, respond to the changing environment and learn.
  7. Be Flexible
    To be truly agile, you need to be able to cross disciplines – leading, coding, testing, requirements, fixing a machine – take it all as part of your daily job. You’ll increase your own learning, and value to the company.
    Be ready to do everything!
  8. Keep Everything Releasable
    If you’re a tester this is easy to understand, if you’re not just imagine you are for a second.
    To test or check progress, you need to see output – whether it’s fully ready or not. You don’t want to be told that you have to wait a day for a build!
    Everything should be ready to pass on at any time. It’s easier for everyone involved.
    It doesn’t need to be perfect, it just needs to be transparent.
  9. The Big Picture
    Understand the business and big picture implications of all decisions.
    This may be done by a Product Owner – (this could be a committee, Requirements Engineers and Architect). If using a product owner concept, use them as a “Customer”
    People need to be reminded of this vision by the Product Owner.
    To forget what the outcome of the project needs to be is the worst type of failure.
    If we keep selling a vision, people will believe.

So there you go – my opinions on real Agility.
It’s all down to the people and their mindset. If you have a team of developers following the above values, you can use any tools/processes that you want, but you will have agility.

I originally posted this article on AgileZone.