I think here we have three different concepts we need to discern between: unit tests,
System.out.println() and the assert keyword. Unit testing is a systematic way to tell whether an application behaves as expected especially when some modifications of the source code are made. Personally, I'm in favor of the following software design strategy:
- Create Interfaces and implementing classes with out body (throwing UnsupportedOperationException)
- Create unit tests
- Implement the interfaces
- Run the JUnit tests
And run the unit tests every now and then to check if everything is as expected. Unit tests should be exhaustive and leave little space for bugs. I point I would like to clarify is that using JUnit does not add an extra dependency in the distribution of your application but exists only locally. Such dependencies are known as "test libraries". Including such libraries (e.g. JUnit or DbUnit) in your classpath is really not recommendable either if you work on a library (so you oblige your clients to have this dependency in their main classpath) or on a standalone executable application such as a GUI (because your executable jar will be larger in size). For example, among people working with maven it is well known that JUnit should be declared as a
assert now, though can be used for testing, its scope is different; assert is a handy way to throw Exceptions and in particular
RuntimeExceptions or AssertionErrors. Though both declare that something very unexpected has taken place, runtime exceptions are not to be used for testing. More, assertions lie inside the source code while unit tests examine the code's behavior on runtime from the client's point of view proving better insight on what might happen when the software is released. While it's good to "assert" some conditions in the source code, overdoing it leads to chaos (a code foul of assertions, admittedly does not look very good).
System.out.println() is used by many along with unit tests to output information to the developer and, alas, this is a very common practice among developers probably because it's very easy to do so. In my humble opinion, this is a bad use of the System's output (whether we are talking about Java or any other programming language). So even in the case we need to do something quick and dirty is better to use the
System.err for debugging or much better use a logger (e.g. SLF4J). My main point though here is that it's very impotent that the developer will go through every singly output of the unit tests to check if it looks as expected (Imaging doing so with tens of unit tests).
So unit test, assertions and System.out/System.err have all their own purpose. Nothing obliges of course the programmer to follow some specific "musts" or go always by the manual (and I don't think anyone really does) but it's good to find those practices that will pay back in the long term and offer you a well-organized and bug-free (as much as possible) source code. And as far as I am concerned, unit tests definitely help towards that direction despite that it's sometimes boring to write an exhaustive test.