19

If you've always loved unit testing, good for you! But for the unfortunate ones who weren't born with a liking for it, how have you managed to make this task more enjoyable ?

This is not a "what is the right way to unit test" question. I simply want to know little personal tricks that reduce the boredom (dare I say) of writing unit tests.

2
  • 2
    I love writing unit tests and other tests partly because just about everyone else kind of sucks at it (sometimes they also suck at making tools that I am testing). No, I do not suck as a developer. I just like usability, eye candy and automation. The MbUnit library has changed my life. Auto testing is important. Auto testing saves time. Auto testing saves money. Auto testing can save lives. Auto testing is the only way. Auto-testing is yet another safety net. When I am one of 50 people working on a huge architecture, I feel like yet another brick in a wall. With unit tests I am in control.
    – Job
    Feb 1, 2011 at 4:05
  • Laziness and frustration at unit testing is a normal reaction to work that our brain perceives as useless. I hate to write and maintain unit tests that have little or negative ROI. However writing useful tests is a pleasant task but it's a skill on its own to recognize what's useful and what is rubbish. There's a guy who's writing a book on this topic based on his blog, you can star reading here: enterprisecraftsmanship.com/2016/06/01/…
    – KolA
    Aug 23, 2019 at 20:22

9 Answers 9

22

Firstly, I agree with you - if you are writing your unit tests on already completed code, or you are manually unit testing your code, I find that extremely boring too.

I find there are two ways of unit testing for me that really make it enjoyable:

  1. By using Test Driven Development (TDD) - writing the tests first allows me to think about the next piece of functionality or behaviour that I need in my code. I find driving towards my end goal in tiny steps and seeing tangible progress towards that goal every few minutes extremely rewarding and enjoyable.
  2. When there are bugs, rather than going straight to the debugger, it's a fun challenge to figure out a way to write a failing unit test that reproduces the bug. It's extremely satisfying to finally figure out the circumstances that make your code fail, then fix it and watch the bar turn green for the new failing test (and stay green for all of your existing tests).
0
13

Smug superiority.

I'm only half-joking. "Look at me, cultivating good programming habits! This 'unit testing' stuff is something Me From Ten Years Ago never would have done -- what a fool! And just think of all the bugs I'm going to catch as a result of this boring, tedious work I'm doing right now -- my code will be awesome! I'll get a raise for sure!*"

* -- No, I won't.

I find it's like working out or eating healthy; until the tangible benefits actually kick in ("Holy balls, I really AM catching a crap-ton of regression errors that would have snuck into production!"), the moral pride of knowing that you're doing The Right Thing can help carry you through.

0
7

For one, I almost never just sit there and write unit tests. Unit tests are a means to an end, not an end in themselves. They are a way of answering "does this code do the basic task that it is supposed to."

For instance, some people will write a function, and then open an interactive session to test it out on a few values and make sure it's working:

def fact x
  if x == 0
    1
  else 
    x * fact(x-1)
  end
end

>> fact 10
=> 3628800
>> fact 7
=> 5040

But now you discover a bug:

>> fact -1
SystemStackError: stack level too deep
    from (irb):2:in `fact'
    from (irb):5:in `fact'
    from (irb):10

So you fix it:

def fact x
  if x < 0
    raise "Can't take the factorial of a negative number"
  elsif x == 0
    1
  else 
    x * fact(x-1)
  end
end

>> fact -1
RuntimeError: Can't take the factorial of a negative number
    from (irb):3:in `fact'
    from (irb):10

But now you really ought to test to make sure it still works:

>> fact 10
=> 3628800
>> fact 7
=> 5040

As you can see, you keep on repeating the same tests... and you have to compare the results visually. Unit testing is a way of avoiding the repetition in this case; it reduces how much work you need to do. And while this is a silly little example, in the real world, it becomes more and more important, and more and more difficult to test manually. What this means, of course, is that people simply don't test the individual components; they just test the whole program. But then bugs crop up, and they're much harder to find. Or bugs happen, and they're fixed, but someone introduces the same bug all over again, because no one added a test case to make sure that didn't happen. Or someone looks at a big piece of code, and says "I have no idea what this is supposed to do, since it's not documented and has no tests... if I fix this bug, I have no idea if I'll break something else depending on it; maybe I'll just rewrite this from scratch."

Unit tests reduce all of the extra work in these cases. The best way to make them fun is to make sure that people understand all of the work that they are replacing, and the extra flexibility that comes from knowing what each piece of code is supposed to do. To some degree, people need to have a bit more experience with writing and maintaining a large code base to understand how important unit testing can be; if all of their code is something they write once and throw away, they'll never quite get it.

And unit tests shouldn't be written after the fact, as an extra chore once you have code that you "know" already works. Unit tests should be written first, or at the very least (since you sometimes forget to write them first) right after writing the code in question. This is called test-driven development, and it can help make your APIs better; if you write the tests that exercise the APIs first, you will learn where the APIs are a pain to use before you even write the code, and can redesign much more easily than if you only add the tests afterwards.

5
  • @Biran, I agree. But all of that makes it the "right" thing to. But how does one make it enjoyable? Even slightly?
    – Preets
    Sep 9, 2010 at 15:07
  • @Preets It's enjoyable because you're avoiding doing repetitive manual testing. It's more enjoyable when you do it first, as opposed to after the fact, because it becomes part of the design process, not an after the fact chore for code that already "works." Sep 9, 2010 at 15:56
  • So, spend time doing it badly, so that doing it RIGHT feels fun by comparison? ... That might work, actually....
    – BlairHippo
    Sep 9, 2010 at 18:27
  • @Biran, I agree, one must do it "first" - not only to eliminate boredom, but I suppose that IS the right way to do in it order to reap the true benefits of unit testing.
    – Preets
    Sep 14, 2010 at 13:57
  • @Biran, Thank you! I recently used TDD on a hobby project of mine and it changed the way I think about unit testing.
    – Preets
    Sep 30, 2010 at 13:50
5

I don't know. What definitely makes unit testing more enjoyable to me is the thought of all the frustrating, lengthy, boring and unrewarding debugging I will not have go through every time I make a change in the software :)

3
  • 2
    That is interesting. Because personally, when someone finds a bug in my code I bury my head in shame, but at the same time, the process of debugging for me is actually quite entertaining and way more fun that unit testing. It is like solving a puzzle where you have to catch that sneaky bug.
    – Preets
    Sep 9, 2010 at 15:02
  • @Preets: I agree, sometimes it can be fun, but for me, design is much more interesting than implementation. Thus I don't like to spend much time on implementation. I prefer it to be straight forward and predictable, especially because it allows making more reliable time schedules. As much as I enjoy the process of creating software, I think the result is decisive.
    – back2dos
    Sep 9, 2010 at 20:20
  • Oh I completely agree! A system with random bugs can cause sleepless nights.. my choice was simply a preference in an unreal world where nothing other than having fun mattered !
    – Preets
    Oct 11, 2010 at 22:46
3

The smug superiority you feel when you check in code that is rock-solid, robust, and stable. And if you write unit tests with a code coverage tool, you can boast in your check in comments that your code coverage is 90% or higher.

3

Obviously, there is the satisfaction of test-first development and the feeling you get when your design and tests come together. However, writing tests for pre-existing/legacy code can be mind-numbing and frustrating. When our project was in a maintenance pattern, I wrote tests for untested code using the coverage report as a game. You can create a bit of a competition with yourself and/or others to boost the coverage numbers. Granted, you might take it too far and create some bad tests, but it can be a good motivator.

1
  • since legacy code is generally not easily testable, I find myself struggling to write good unit tests - so not only is the process painful, but the result (unit tests) aren't particularly useful either :-/ I find that most frustrating... The coverage game is a good one though :)
    – Preets
    Oct 11, 2010 at 22:31
1

Try to get into the Flow. Set tough, but achievable goals to yourself. What could be a goal in unit testing? For example, try to write faster while keeping quality. Unit tests don't require too much thought so mistaking is unlikely. Concentrate on your goal and check often to see as you are nearing it.

2
  • ás, why do you say unit test do not requite too much thought? If you work with TDD it does involve a lot of thinking. Is that not true ?
    – Preets
    Oct 11, 2010 at 22:33
  • You are right, I didn't take TDD into account. Oct 12, 2010 at 7:59
0

Sometimes to get myself motivated, I'll write down my current "code coverage" at the start of the day. Then each time I write a test and get it to pass, I'll run the suite, and update the coverage number. It's fun, and it helps remind me why I'm doing this. (There are other reasons too, but I like the numbers. Maybe that is just me!)

0

By not trying to delude myself that I can trick my mind into thinking that unit testing can be enjoyable for any sustainable period of time.

Accepting the reality that unit testing is not there to be enjoyed helps me a great deal, making me realise that I am looking for something in a place where it was never supposed to be.

In these brief mental excursions when I get to the point of perceiving unit testing to be what it really is, i.e. a cruelly, unbearably, and soul-crushingly boring task, I ask myself whether I can afford letting go of them, i.e. not having high guarantees about functional correctness.

Invariably, the answer is a resounding "no".

Upon accepting my fate, I keep pushing these square objects with letters, numbers, and symbols on them in front of me, which we call keyboard, knowing from first hand experience that with each keyboard click, the end of unit testing is closer than it has ever been.

2
  • Not every test is good or useful. This is something that TDD'ers and other test evangelists usually don't mention. I bet in some rare moments you do enjoy unit testing when you know that it tests complex logic, test is elegant and not coupled to implementation, and rather hate when you being forced to test trivial crap only to achieve some lunatic code coverage target required by project guidelines.
    – KolA
    Aug 23, 2019 at 20:39
  • @KolA You are right that there are challenging unit tests that require creativity, but writing endless unit tests can suck the joy out of even the innately interesting ones.
    – bugfoot
    Aug 26, 2019 at 15:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.