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.

Author: johnjvester

IT professional with 30+ years expertise in app design and architecture, feature development, and project and team management. Currently focusing on establishing resilient cloud-based services running across multiple regions and zones. Additional expertise architecting (Spring Boot) Java and .NET APIs against leading client frameworks, CRM design, and Salesforce integration.

One thought on “Unit Testing … worthwhile or a waste of time?”

  1. John,
    I don’t have as much experience writing unit tests as you do, so I appreciate your post and find your observation on the usage trends for adopters to be interesting. I would like to share some of my thoughts after reading this post. I welcome feedback.

    In your section “Worthwhile or a Waste of Time?”, you say “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.” If writing unit tests is determined to be worthwhile, it definitely would be a mistake to suspend this practice in the interest of time, unless this is intentionally done at the cost of quality. It seems less likely this practice would be suspended when it is known that quality will be affected for the remainder of the project. A better choice would likely be to reduce the scope.

    But, how do we measure the benefit received from unit testing to determine if it’s worthwhile? We could compare the average time spent writing code without unit tests and fixing the resulting bugs to the average time spent writing code with unit tests and fixing any remaining bugs. Choosing to write unit tests is a commitment to increased initial cost with an expectation that the project is large enough to cross the break-even point and save time and money in the long run. I found an article that also points out how delaying the deployment of critical functionality in order to write unit tests can be costly in terms of lost productivity that could have benefited from the delivered functionality, even if it was buggy. It also suggests situations in which unit testing has been shown to be valuable. Overall, I enjoyed it even though it contains a small plug for a product.
    https://www.simple-talk.com/dotnet/.net-framework/unit-testing-myths-and-practices/

    I wonder if another reason why some developers eventually stop writing unit tests is because they don’t find them as relevant as they had hoped. If so, my follow-up question would be “what are you testing”? If you’re testing conditionals based on constants, you’re probably wasting your time. But I find unit tests are valuable when they check output based on variable input or third-party libraries which are subject to change. The tendency is to not write unit tests for those methods which you feel confident are bug-free and handle all corner cases. But do those feelings come from experience and humility or from arrogance or laziness? I write unit tests not only for myself, but for those that come after me, as you said, as additional documentation. Writing unit tests and seeing some of them fail helps me learn from my mistakes quickly and apply this knowledge to future problems.

    In general, I think it’s up to the organization and team to find the right balance of unit testing based on the skill level of the developers, the fragility of the language, the scope of formal testing (and whether it’s automated), and the estimated lifespan of the application.

Leave a reply to Chuck Eastus Cancel reply