Oct 02 2007
Between TDD and Java code comments
The last day before China National holiday, I got the chance to learn TDD from Hu Kai who is a main contributor to CruiseControl and CruiseControlEnterprise.
Basically, we made up an example for practicing. A good example for TDD exercises is “develop a calculator”.
- First thing, we did was write a JUnit test for calculator project, based on requirement
As a user, I want the calculator to have absolute value function, so that I can carry complex calculations.
with one of the three acceptance criteria.
- Then run the test. When we saw the test failed, we know that it was time to develop some functions to make the test successfully.
- After we accomplish the the code part, then re-run the test. This time test passed
- It is not done yet. Add one more test case, run test. Failed, then improve the code.
- When we added the last two test cases, test would not fail so it meant that our function was achieved based on the requirement.
- Next step refactoring code. Done. The code looked neat and pretty
But it looked something missing…… Ah! Comments! Yes, I remembered that the first thing my teacher taught me in Java programming was “Don’t forget writing down your comments, otherwise people would not understand them.”
Hu kai, why did not write some comments in your code?— Xiaoming
You don’t have to because all the tests and code are self-explaining and highly comprehensive.— Hu Kai
Then people in the room had a discussion when should we have comments in Java code with Agile practice. My idea was that for those legacy system, if there were no comments or documents, how could people understood them? Different opinion was to write as high-level self-explaining code as possible. For example, make the names of classes, functions human-readable. I would buy their ideas except in some cases, comments are necessary
- Interfaces, libraries. Yes these abstract information need comments to help programmers to understand how to use them. We might call it “User guide” rather than comments.
- Complex algorithm. It would be very difficult for programmer to understand without spending much time on it. So it’d better to have comments for the brief explanation of this section of code.
Meanwhile, functions should be as simple as possible so you don’t have to write comments for complicated ones. Basically breaking down complex functions into simple ones would be a good idea.
All in all, when we initiative to learn something, it always came to the end with more knowledge and experience in your pockets. What a brilliant enthusiasm of learning!
Unfortunately, in most of the university classes and labs, students have not got chances to do useful exercises like this. I highly recommend doing more in our universities classes or labs.
~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.
According to Lingling’s question, let me give a real example. Firstly list the three acceptance criteria.
Given a positive integer A ,When I calculate it with abs function, then I get the same number A.
Given a negative integer “-B” ,When I calculate it with abs function, then I get a positive number “B”.
Given number “zero” ,When I calculate it with abs function, then I get zero.
Let’s write the first test case: My idea is to show the logic so it would not be the real code
Public boolean testAPositiveNumberShouldReturnPositiveNumberWithSameValue(4){
if(object.abs(4)=4){
return true;}
else{
return false;
}
}
When we have this test case for acceptance criteria one, and run the test. Obviously, the test failed because we do not have the function abs yet. So let’s try to write some code to make the test pass
Public int abs(a){
if(a>0){
return a;
}
}
Build the code, once you run the calculator tests, it will pass because the method provide the function of test “testAPositiveNumberShouldReturnPositiveNumberWithSameValue”
Then we add another test case based on Acceptance Criteria two
Public boolean testANegativeNumberShouldReturnPositiveNumberWithSameValue(-4){
if(object.abs(-4)=4){
return true;}
else{
return false;}
}
When you run the test, you can imagine that the test failed.
It is time for you to write some code to fix the fail test. Can you do it? OK let me do it for you:-)
Public int abs(a){
if(a>0){
return a;
}
else{
return -a;
}
}
Build, run test, Yeh!!!! Test passed!!! Even when u try the third test case, it passed either. It means that you don’t have to write more code about it. This is the beauty of TDD
Next step code refactoring. You may use Math.abs() to replace that piece of code
So, let’s answer your question one by one:
- Is each test case designed to test one of the three acceptance criteria?
- How do you define the test is “failed”? e.g. If the result data is not “exactly match” the expected data? or the test doesn’t run properly?
- Why did you “pass” this test with only one test case for each requirement?
The answer is “Yes” You can write the three test cases all together. However I highly recommend to write each by each.
I might not need answer this question. If you do not have the function to satisfy the JUnit test, the test would definitely fail. If you are familiar with Eclipse you might easily understand what I am talking about.
The beauty of Agile is to do every little bit each time then increase little by little. As soon as you find out that no more code is needed, the job is done!!
About the function: one function (in Java, one method) should only do one thing and do it well. Otherwise, break it down. About the comments, I believe documentation comments are very important and we must have them. Inline comments can be eliminated by high-quality code.
Questions: I understand that in TDD you write the test cases before you write the code. In your test, you run totally 4 test cases.
1. Is each test case designed to test one of the three acceptance criteria?
2. How do you define the test is “failed”? e.g. If the result data is not “exactly match” the expected data? or the test doesn’t run properly?
3. Why did you “pass” this test with only one test case for each requirement?
Thanks.
Many thanks for your comments, Lingling!
When we do agile, the last thing that we want to do is “documentation”. We do not have much design documents except they are necessary. For software architecture, we use diagrams and photos that were taken during the architecture discussion. We do have documents like “user guide” or “read me”. However, as the application that we developed have rich usability, and well designed so sometimes even documentation is not necessary. It vary case by case. Roughly speaking, compared to Waterfall model, agile software development has much less documents.
For your questions, I’d like to give you an real example for explanation, please have a look at the post context if you still have questions please feel free to ask.