Wednesday, August 24, 2011

Organizing unit tests

I have been using a different approach to organizing the unit tests and this have turned out to be very effective. Worth sharing.

So if we have a class that looks like:
public class AccountService {
  public void getAllAccounts() { ... }
  public void createAccount() { ... }
  public void removeAccount() { ... }
}

For such a class we would traditionally have a unit test class called AccountServiceTest and all the test cases for all methods mentioned above. We would also have a bunch of global variables in the Test class and a setup (@Before) method.

My different approach involves creating a unit test class for each method rather than just one test class. So now we would have three classes:
public class AccountService_getAllAccounts_Test {}
public class AccountService_createAccount_Test {}
public class AccountService_removeAccount_Test {}

Generalizing it the unit test class name should be:
<<class under test>>_<<method under test>>_Test.java

Each class would have test cases for only the method referenced in the file name.

So how is this approach effective?

SRP - Single Responsibility Principle - is restored
In the traditional way the SRP principle is violated with the setup method as it is now common to all the test cases for all methods for the class under test. The setup has responsibilities to setup the objects and data for all the test methods for all methods in a class. Even the Test class has multiple responsibilities to test all methods in there. With the new approach every test class has responsibility to test only one single method under test.

"Look and Feel" of unit test cases
This is more of a perception thing but it works. Say if every method under test can have 5 unit test cases, in the above example having a single test case class means we already have 15 methods in there. When a developer looks at a single class with that had large number of methods with a single setup method that looked cryptic and they were less likely to update any unit test cases or even add more tests to them. When the classes were separated the "look and feel" of the test cases improved developers are now willing to and able to extend existing code base by adding new test cases.

What are the side effects of this approach?
  • Popular plugins like moreunit do not work anymore
  • Proliferation of Test classes may be something some developers may not like at first.

Let me know what you think !!!

Monday, July 25, 2011

TDD and Technical Debt

So whats the relation between Test Driven Development and Technical Debt?
  1. Technical Debt is a term inspired from Financial Debt that people fall into
  2. People fall into Financial Debt when the spending to earning ratio gets out of order, spending more than money earned.
  3. In most cases spending more than limit is because the concept of monthly finance budgets is lacking or not enforced.
  4. The monthly budget that is setup at the start of the month or year is like writing unit test case. Then living the month by the budget is like writing exactly the code needed for the test to pass.
Hey -- so just like in real lives lack of Test Driven Development or not enforcing it does cause more Technical Debt.

Wednesday, July 6, 2011

moving to github

I am moving all my code from presentations / pet projects to github -- http://github.com/daveayan
So far I have migrated 3 projects but more are coming. So far this is what I have:

- Google App Engine Presentation I did in April 2010
- Maven in Polyglot space presentation from Columbus Polyglot user group (03/2011) and QSI Tech Lunch (05/2011)
- My pet project rjson that is a core piece for my legacy code testing project (coming soon on github)

Tuesday, July 5, 2011

Need to start blogging again

It has been so long. I need to start blogging again. More stuff coming here.

Saturday, February 13, 2010

Why do we need unit tests?

Alright ... the TDD & CI analogy is good. Makes sense the way it is described. But how would you justify spending time and money on writing unit tests when you are under tight budget schedules. Why would you even need unit testing when we have a v good QA and Testing team and as good processes in place? This is an often asked question. Here is what I think.

Unit tests are not meant to rule out the need for QA / Testing. Unit testing is not even meant to complement QA / Testing, although they would help significantly reduce the burden on QA team. They are there for the developers. Let me give you an example - but first, put on your developer caps. I have a BaseDao class that has a query method on it like this:

public List<Object> query(String sql)

The method takes a SQL query as input and returns back a list of objects mapped from the query result set. The more important part is that the method returns a null back if no records were found in database. Now I have atleast 20 DAO's that extend this BaseDao and use this query method atleast 100 times.

Now in all good mind and after lot of consideration it was decided that the query method in the BaseDao will have to return a empty list (new ArrayList<Object>()) back instead of null if no records were found in database. Sounds like a easy change, but now what happens to all the 100 methods out there using this method? What happens to all those if conditions with null checks after the query method? For example: One of the DAO's has these lines of code that will break for sure.

List<Object> l = query("SELECT * FROM PERSON")
if(l == null)
  return false;
else
 return true;

How does a QA / Testing team plan to test this change in the system? This would become even interesting if there is a DAO method among these 100 that will be called only rarely in certain special data combinations only. Does the testing / QA team know what that method is and when is it called? The real idea with unit testing is to help the developers. If we have all these 20 DAO's and 100 methods all tested well it will be easy to find where the code would break when such a change takes place.

Another important point is that these lines of code continue to live as long as the system lives. The QA / Testing team moves on and the next time there is a new feature development / major bug fix the same QA team may not be there even. Even the same developers wont be there working on the system. Now consider this scenario - as a new developer you are put on such a project and you have to fix a defect. This method you need to fix is being used by 10 different classes from web and batch projects. How can you update this method confidently without breaking the functionality offered by all the other 10 classes? And you need to think of this even before the next QA / Testing team comes in to start testing the system.

Of course for developers, just like any other technology, there is a learning curve and it can be difficult. Specially with tight deadlines and with agile processes you may not get a lot of time to learn TDD. But who said life would be easy. Once the learning curve is conquered things become easy.