In this second part of the "TDD series" Wellie Chao looks at the advantages of JUnit as a testing framework, overviews essential testing concepts and terminology, and walks you through writing a sample JUnit test case. Upcoming articles include: Unit Testing of EJB components, Black Box and In-Container Testing of Servlets and JSPs, and In-Container Testing of Struts Web Applications.
- Posted by: Nate Borg
- Posted on: January 14 2004 13:18 EST
Read Test-Driven Development Series Part II - Testing Java Classes with JUnit
- This is not TDD either by Aslak Hellesøy on January 14 2004 16:41 EST
- Quality of Test Classes by Michael Mahemoff on January 14 2004 17:41 EST
- Agreed on examples by Dave C on January 15 2004 11:35 EST
- Agreed on examples by Aslak Hellesøy on January 15 2004 16:18 EST
- Agreed on examples by Richie Bielak on January 16 2004 11:50 EST
- How to test database operation with JUnit? by Holen Chen on January 16 2004 11:32 EST
- TDD Reflections from the UnitSide by Kent Mitchell on January 16 2004 16:58 EST
- Alternative tutorial by Marie Antoinette on January 19 2004 05:15 EST
Just like the previous article in TSS' "TDD Series", this article doesn't touch upon TDD at all.
The people who chose the name "TDD Series" for this article series seem surprisingly clueless about what TDD is about. (I don't know if it is the article author or the TSS editors, but it gotta be someone).
Do yourself a favour: Read up on TDD or remove "TDD" from the article series name.
Some more useful examples to the general programming community would be good. There's probably not millions of people out there who care about calculating prime numbers or whatever. What about some example tests for database access code or some such?
A starting point for a JDBC example:
The featured test case - CalculatorTest - does the job to an extent, but does not support iterative development. To be fair, this article does allude to a notion of TDD by showing how to create a broken test case and then fix it (although a TDD process would usually begin with a test case rather than an existing application class!)
However, a test class like CalculatorTest makes it difficult to iterate between test and app code, because the test is difficult to maintain - it contains a large amount of cut-and-pasted code and is in need of some serious refactoring.
Every time I read some article about using JUnit, the code being tested is always some bullsh*t math thing that NO ONE ever does. Then, when I try to use JUnit to test some real stuff, it ends up being a monumental mess of unmaintainable code, completely coupled to the code being tested, and an utter waste of time compared to just testing manually. Now, while most Java Process Zealots are pretty out of touch with the real world, I have to assume that someone who's actually smart with real-world experience thinks JUnit is useful and saves time. So, why can't we get an example of that? And that example should includ what happens when you need to make changes to the code under test.
I have outlined some counterarguments about the common "TDD takes more time" argument here: RE: Enough with the Test Driven Development Hype.
If you think the process zealots are advocating that unit testing tools (like JUnit) should be used to ___test___ existing code, you have misunderstood completely. They are saying that these tools should be used in order to ____develop____ code that doesn't yet exist. What do you think the D's in TDD stand for?
Also see: TDD is like teenage sex.
Aslak Hellesoy - Any Language Process Zealot.
The classic argument to any nay-saying of TDD: You just don't understand it.
Your "counterarguments" basically amount to just disagreeing with the various points you outline.
The fact is that sometimes one must implement hugely complicated business logic and there is no way to simply test that. The project I'm working on now has such a complicated business process that test DATA to get even remotely decent coverage was huge. There's something like 40 or 50 unique paths through the code.
So, a JUnit test case to test that is gonna be HUGE and it's gonna be complex, and in the end. For JUnit or Manual testing, I still have to come up with test data. Once I've got that, it's 10000 times easier to just run the tests myself. If I had written JUNit tests beforehand, I would've wasted huge amounts of time and not bought myself much of anything.
And, hey, you are free to provide a real-world example; yet I never see one.
So, a JUnit test case to test that is gonna be HUGE and it's gonna be complex, and in the end. For JUnit or Manual testing, I still have to come up with test data. Once I've got that, it's 10000 times easier to just run the tests myself.
I also find that with JUnit I can catch trivial errors only (I am talking about end-user applications, not generic libraries or db frameworks). Maybe it's important in the environment where develpers change often and don't have time to understand how the application works. However, the most difficult to find and costly bugs are in the application's business logic. Yes, I can write tests to test business logic as well, but before I do that I must come up with such data that will fail the test. The moment I come up with such data, I simply correct the code to deal with such data correctly: in this case writing JUnit tests becomes a mere substitution for developer documentation and this substitute is hard to maintain.
And I'm too wondering why the TDD advocates don't provide examples to support their strongest points. All samples I've seen are simplistic test cases that do not apply to real situations.
The problem here, I think, is that TDD is not equally applicable to all software being developed. There are categories of software where using TDD don't bring much benefits.
"So, a JUnit test case to test that is gonna be HUGE and it's gonna be complex, and in the end. For JUnit or Manual testing, I still have to come up with test data. Once I've got that, it's 10000 times easier to just run the tests myself. If I had written JUNit tests beforehand, I would've wasted huge amounts of time and not bought myself much of anything."
The benefit of a JUnit suite of tests is not to save time during the initial development cycle but rather to save time and ensure consistent quality in all subsequent development cycles by being able to run an automated suite of tests.
Yes there is a maintenance overhead, and yes the initial task of writing them can be significant in any reasonable system, these need to be factored in to development schedules.
Agree in general but sometimes TDD approach forces better understanding of how code should work. It may increase a speed of development at initial stages, especially when disign is forming. For instance you can take a look at this sample of Test Driven Development. Unit tests rise attention and improve code quality.
I've been using JUnit in real world projects for few years now. In fact I'm writing this while my JUnit test suite is running (it takes about 5 minutes). If you want to see some real tests take a look at an open source library I maintain called Abra (it's another Java/DB persistence layer with code generations). We have handful of JUnit tests to test new releases. See http://http://abra.sourceforge.net/.
My current at work project has a suite of about 60 tests and growing.
Your example is smart,but can you talk about how to test db operation or IO operation with JUnit,thx.
I think this article exposes some interesting issues that I thought were worth discussing. First, adopting TDD is not trivial as is shown by the comment about this not really being a TDD posting. Second, even a good set of unit tests can miss serious bugs. The test cases provided do not fully exercise the code and fail to expose and infinite loop in the factor() method. I posted some information on this on developertesting.com in a a blog entitled TDD Reflections from the UnitSide
Ok, it seems averyone has been quick to jump on the relevance of this article, as compared to "true" TDD. Would anyone like to back it up by pointing us in the direction of an article that articulates just what the TDD philosophy is (apparently) about? Can there not be degrees of TDD? Just as there are degrees of XP?