9

I have a few medium-sized Rails apps that I work on routinely, and only one of them has any unit tests at all. But I have seen the light and I want to change all that, except... I don't have the time to go in and starting writing tests class by class or something like that.

How do you start writing unit tests on an existing -- and working -- codebase with limited time? For example, since any approach would have to be incremental, how would you order your unit-test writing? Start with superficial tests, then move on to more coverage, or cover just a few classes... etc.

Note: I am asking this question thinking about Rails, but really I'm interested in how it applies to any language.

Edit: Note, this question is not the same as this other one. The other one asks how hard this is, and was the result worth it. I'm asking about how to add unit tests.

Community
  • 1
  • 1
Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421
  • +1 Interesting. But this is a general question, not specific to Rails. Would you mind rephrasing it so? – amit kumar Mar 09 '10 at 19:04
  • Amit Kumar, no problem, doing that now. – Dan Rosenstark Mar 09 '10 at 19:05
  • 1
    "How do you start writing unit tests on an existing -- and working -- codebase with limited time?" This is a duplicate question. http://stackoverflow.com/search?q=%5Bunit-testing%5D+legacy. Start with http://stackoverflow.com/questions/1541568/adding-unit-tests-to-legacy-code – S.Lott Mar 09 '10 at 19:09
  • Thanks @S. Lott, that question is not related (much). This one isn't related either http://stackoverflow.com/questions/748503/how-do-you-introduce-unit-testing-into-a-large-legacy-c-c-codebase but I'd be glad to find one that is so this one could be closed. – Dan Rosenstark Mar 09 '10 at 19:17
  • @yar: If they're not related, then fix your question to clearly state how these other -- existing-- questions that look identical are not identical. Please identify some *specific* details that make your question different. – S.Lott Mar 10 '10 at 14:09
  • @S. Lott: The other question asks, "have you ever done this, how difficult was it, and was it worthwhile." I'm asking HOW to add unit tests to an existing codebase with limited time. But I'll revise my title, yet again. – Dan Rosenstark Mar 10 '10 at 17:15
  • @yar: The accepted answer says "The best way, I have found, is to incrementally add the unit tests, not to just jump in and say we will now unit test the application" and references http://stackoverflow.com/questions/748503/how-do-you-introduce-unit-testing-into-a-large-legacy-c-c-codebase. It sounds like that is your answer. – S.Lott Mar 10 '10 at 19:45
  • @S. Lott, yes you're 100% right. Please feel free to mark the question for closing. – Dan Rosenstark Mar 10 '10 at 23:47

7 Answers7

10

Here is how I usually start adding unit tests to a project that didn't start out that way: Wait for someone to file a bug, then write a unit test that reproduces the bug. Then fix the unit test. This not only starts building unit tests, but now no one can accuse you of a regression for the given bug.

James Kingsbery
  • 7,298
  • 2
  • 38
  • 67
5

My answer isn't specific to Ruby on Rails. Next time you need to touch the codebase, to fix a bug or add a new feature, write tests for the parts of the code you're touching. If you can spare a couple of minutes, add some related tests. If you find that you need to refactor, go ahead and write the tests to support that. Over time you'll build up the test coverage, and you'll find you always have tests for the areas you need them in (because those are the tests you're writing).

  • 1
    Keywords here - "if you can spare a couple of minutes". As I've noticed, projects without unit tests aren't unit tests friendly at all. Those minutes could grow into hours and days rapidly. – Arnis Lapsa Mar 09 '10 at 19:33
  • @Arnis L., as I've mentioned in my comments to another answer, dynamically-typed languages are friendlier than others, so you can always make things fit. That said, I'll check back in a few months and see if I still think that :) – Dan Rosenstark Mar 09 '10 at 19:45
  • @Arnis L. the reason your other post was downvoted is that we assumed that you were joking. It's actually an interesting answer, if you want to put it back, please. – Dan Rosenstark Mar 09 '10 at 19:46
  • @yar i undeleted just because You said it was interesting. but it's quite useless - you didn't ask if unit testing is necessary and i kind a forgot that we are talking about ruby. dynamic languages almost forces You to write tests so omitting them isn't an option as i thought it might be (that could actually help for some cases). – Arnis Lapsa Mar 09 '10 at 19:53
  • @Arnis L., there's an answer in there somewhere (in the newest version). You might just want to move stuff around in your answer using the "edit" button. – Dan Rosenstark Mar 09 '10 at 20:05
5

I had a very similar experience a few years ago, and stumbled upon this book:

Working Effectively With Legacy Code by Michael C. Feathers

It has an incredibly complete set of techniques for starting with an existing codebase that has no unit test coverage, and gradually getting it under test. If I could recommend only one book on TDD, it would be this one.

Hopefully this helps... best of luck!

Tyler

Tyler
  • 859
  • 1
  • 8
  • 10
2

One of the problems I faced when I started writing real unit tests (with mocks and etc) is that I had to go back and change the code to support the injection of the mock objects mostly through the extraction of interfaces. I believe it will be pretty hard for you to do that on an existing system without some sort of refactoring.

Otávio Décio
  • 73,752
  • 17
  • 161
  • 228
  • @yar - C#, but I suspect the same to be true of other languages. – Otávio Décio Mar 09 '10 at 19:30
  • 1
    Not sure about that: I believe that the more dynamically-typed the language is, the easier it is to add more unit tests. Ironically, the more necessary they are too, because you get no compile-time safety. I'm not really convinced about tests for Java, but for Groovy I'm sure that I cannot live with them (though I have thus far). – Dan Rosenstark Mar 09 '10 at 19:32
0

Increasing code coverage is an excellent way to get a new recruit familiar with a codebase.

Other than i think you just need to find time, there is no magic solution!

Paul Creasey
  • 28,321
  • 10
  • 54
  • 90
0

In the long run, unit testing should make getting (working!) functionality to the users faster.

If it's not accomplishing that, it's not worth the time.

Dean J
  • 39,360
  • 16
  • 67
  • 93
  • 1
    trying to avoid the debate on Unit Testing in this question. But while we're here, I think that with a dynamic language like Ruby, you must Unit Test. – Dan Rosenstark Mar 09 '10 at 19:30
  • @Arnis L., no: I think your answer is worth something. But perhaps not for this question :) – Dan Rosenstark Mar 09 '10 at 19:49
  • @yar it's just the same idea that one should know all or at least most options (even those that usually sounds completely wrong) before he continues instead of picking first one that kind a fits. – Arnis Lapsa Mar 09 '10 at 19:57
0

With limited time? Facing deadlines?

Forget about unit tests!

Cowboy coding 4 the win!

Hack features together until it's not too late and client haven't sued Your company.

P.s. For your own safety - do not forget to inform about situation your PM.


Strange that down votes avalanche haven't started yet. Maybe it's not so bad and telling NOT to write unit tests ain't such a taboo at all.

I'm in similar situation (assuming Your time is really limited). What i do - i don't think about unit tests most of the time. But for some cases - it's actual easier to do TDD than to continue hacking (emm... duct taping? :D ) everything together (usually when testable unit has high complexity or is hard to test manually), then i just switch my mind and code normally. In short term - i will be able to understand what i wrote month ago and that won't make much trouble. Problems will arise when project will slip into maintenance phase. But it's still way much better than telling client that you worked on tests and got nothing new.

When you need to start unit testing in existing project - start with your own functionality. Create necessary test infrastructure (if time allows - continuous integration too) and don't forget to teach unit testing to your co-workers.

Worst thing you (or PM) can do - to force writing unit tests to someone who does not know how to do that. That's just wasting time. Lead by example. Gradually.


It did start after all! ^_^

Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195