views:

222

answers:

8

Our project contains 2600 class files and we have decided to start using automated tests.

We know we have should have started this 2599 class files ago, but how and where should large projects start to write tests?

Pick a random class and just go?

What's important to know? Are there any good tools to use?

+14  A: 

Write a unit test before you change something, and for every bug you encounter.

In other words, test the functionality you are currently working on. Otherwise, it is going to take a lot of time and effort to write tests for all classes.

Sjoerd
+1 for _every bug you encounter_ Write a test case that demonstrates the bug, then do the fix, then see that the test case passes.
Tony Ennis
+6  A: 

Start writing tests for each bug that is filed (Write the test, watch it fail, fix the bug, test again). Also test new features first (they are more likely to have errors). It will be slow in the beginning, but as your test infrastructure grows, it will become easier.

If you are using java 5 or higher, use junit 4.

Learn about the difference of unit tests, integration tests and acceptance tests. Also have a look at mocking.

Arian
+2  A: 

Don't try unit tests first. Do system tests (end-to-end-tests) that cover large areas of code. Write unit tests for all new code.

This way you stabilize the old code with your system regression tests. As more and more new code comes in the fraction of code without unit tests begin to fade away. Writing unit tests for old code without the system tests in place will likly break the code and will be to much work to be justified as the code is not written with testability in mind.

Arne
The other possibility when retrofitting old code with unit tests is that you write the unit tests to pass (since the system already "works") and end up validating incorrect behaviour.
Mark Peters
@Mark Peters: IMHO that's fine, in a huge system, there are always somebody relying on the incorrect behavior. By writing the unittest so it passes the incorrect behavior, when you correct the incorrect behavior, the unittest might warn you that the change may affect someone else's code (and then it's design decision whether to break the backward compatibility or not).
Lie Ryan
That's a good point Lie. You can defer figuring out what's "right" and what's "wrong" until a change needs to be made. Best to flag those types of tests though, since unit tests are generally supposed to *specify* correct behaviour, not just protect against functional changes.
Mark Peters
+1 for mentioning the agony of _the code is not written with testability in mind_ Whether one TDDs or not, the tests really need to be written more or less in parallel with the code.
Tony Ennis
+3  A: 

Other answers have given useful advice, but I miss a clear articulation of the underlying principle: strive to maximize the benefit from your efforts. Covering a large legacy codebase with unit tests to a significant extent takes a lot of time and effort. You want to maximize the outcome of your effort from the start. This not only gives valuable feedback early on, but helps convincing / keeping up the support of both management and fellow developers that the effort is worth it.

So

  • start with the easiest way to test the broadest functionality, which is typically system/integration tests,
  • identify the critical core functionality of the system and focus on this,
  • identify the fastest changing/most unstable part(s) of the system and focus on these.
Péter Török
+1 for _strive..._ Pragmatism is good.
Tony Ennis
+1  A: 

You might find this book relevant and interesting. The author explains how to do exactly what you ask for here.

http://my.safaribooksonline.com/0131177052

Thorbjørn Ravn Andersen
+2  A: 

You may find Michael Feathers' book Working Effectively with Legacy Code useful.

jacobm
yes, this is a great book
Ray Tayek
+1  A: 

You're fairly dorked now, but write tests that bolster the most critical code you have. For example if you have code that allows functionality based upon users' rights, then that's a biggy - test that. The routine that camelcases a name and writes it to a log file? Not so much.

"If this code broke, how much would it suck" is a good litmus test.

"Our internal maintenance screens would look bad on IE6" is one answer. "We'd send 10,000,000 emails to each of our customers" is another answer.

Which classes would you test first, hehe.

Tony Ennis
A: 

Oh, and one more thing - having an insufficient number of unit tests is far better than having none. Add a few at a time if that's all you can do. Don't give up.

Tony Ennis