Unit Testing … worthwhile or a waste of time?

me5The idea of Unit Testing has been around for quite some time.  Adapatibility seems to vary – both at the client level and within time periods for a given client.  The biggest trend (for adopters) I’ve seen is heavy usage of Unit Testing for a period of time followed by heavy discontinuation of Unit Testing.  This leads me to wonder if Unit Testing is still worthwhile or just a waste of time.

What Is Unit Testing?

To briefly walk through what Unit Testing is all about, consider the following (very simple) example:

public void processStudent(Student student) {
   // Get current course list for student
   List courseList = studentService.getCourses(student);

   for (int i = 0; i < courseList.size(); i++) {
      Course courseObject = (Course) courseList.get(i);
      determineGrade(courseObject);

      // Other tasks for the list of courses
   }

   // Other tasks for the student being processed
}

private void determineGrade(Course courseObject) {
   // Will determine grade based upon several factors
}

The program code noted above is intended to process various events for a student.  One of those events would be to get a list of the current courses the student is taking and the other would determine the grade for each course.  So, the entry point would be the public method called “processStudent” and it would call the private method “determineGrade” which would update attributes of the Course like the letter grade (A, B, C, etc) and the grade percentage (i.e. 97.9%).

The goal of Unit Testing would be to build scenarios using program code that would make sure all the situations are covered.  The simplest way to think about this would be to consider the “determineGrade” method.  Certainly, we would want to have a test case that would validate the correct letter grade is returned.  So, there would be a test that makes sure a letter grade of A is returned when expected.  The same would be true for the other letter grades.

We might even want to include a test case for every edge scenario too.  In this situation, perhaps we would consider the grade percentage.  Maybe a 94.9% grade percentage would be rounded up to a 95%, which might be the cut off for a letter grade of an A.  So, one test would use 94.9% yielding a grade of an A, while another might use 94.8% (or whatever the cut-off rule becomes) to leave the grade at a B.

What’s the Benefit?

Unit Testing is intended to provide the following benefits:

  • Allow the developer to validate the program logic is functioning as intended.
  • Catches issues before the logic is released for testing, avoiding wasted Tester time.
  • Helps to document the program code’s intentions.

One other benefit to bring up is that Unit Tests can be part of the build/deploy process.  So, before program code is delivered into the Test environment, all the Unit Tests that exist can be executed.  If they fail, the deployment to the Test environment is suspended.

The benefit to taking such an approach is that Unit Testing can catch unexpected problems when a change was made.  Using our example above, perhaps a change was made to something with the Course object.  Doing so caused the logic in the determineGrade method to require updates which were not made.  As a result, the test results started failing and ceased the deployment to the Test environment – avoiding having the Tester test an environment that was already known to have issues.

Worthwhile or a Waste of Time?

From a programmer’s perspective, I believe Unit testing will always have a place in the software development life-cycle (SDLC).  Within the last couple of weeks, Unit Tests that I have written uncovered minor issues with the logic that has been developed.  In one case, a logic condition was actually removed because it would only generate a business exception – since there was not a valid way to fall into that scenario.

However, decisions are not always made from a programmer’s perspective.  Given the investment required in building valid Unit Tests, this time is often the first to be cut when a project needs to meet a certain deadline.  As a result, I believe this is how the “heavy usage of Unit Testing for a period of time followed by heavy discontinuation of Unit Testing” situation (noted above) is born.  Unfortunately, recovering from this situation will likely take more time than if the Unit Test programming wasn’t suspended in the first place.

Advanced Topic – Private Method Testing

One last item I wanted to bring forward, is something I introduced on my current project.  That being the concept of writing Unit Tests at the private method level – and not just the public method level.

In the example above, the processStudent method was a public method and available for Unit Test frameworks to see without any issues.  The method is public and available to all who have access to the program class.

However, the determineGrade method is a private method.  Basically, the logic in this method was not intended for other classes or services to utilize. So, the decision was made to hide this method and make it private.  Out of the box, Unit Test frameworks cannot see these methods.

With my current project, there are several private methods that are used multiple times.  Instead of writing Unit Tests against the public methods, I wanted to write Unit Tests which would fully exhaust all the permutations for the private methods.  Then, I would only have to write Unit Tests to fully test the code at the public method level.  Doing so, would actually a) cut down on the number of Unit Tests that were truly required and b) provide better documentation to understand the desired intent at the method level.

Using Reflection and a great article by Bill Venners, I was able to accomplish my goal.  In fact, a utility class called TestPrivateMethod was created to contain the common elements for other Unit Tests to use.

Conclusion

I hope this blog, while long and a bit technical, was a worthwhile read.

If possible, I would like to hear from you either via comments or using the poll listed below.

Advertisements