Good Quality Unit Tests

Every successful startup understands the importance of well-written software, but not all realize the critical role that quality unit tests play in the overall product life cycle. Today, we'll explore the attributes of a good unit test and discuss the significance of elegant unit test code for startups looking to scale.

Characteristics of a Good Unit Test

A high-quality unit test exhibits certain key characteristics:

  1. Idempotent: A good unit test can be executed repeatedly with consistent results. In other words, it should always return the same outcome, irrespective of the number of times it's run.
  2. Independent/Atomic: It should not depend on any other tests to run before it, nor should its execution order within a test suite matter.

Meeting these two attributes prevents your unit test from becoming flaky, which can lead to test failures, ultimately resulting in test neglect or removal.

Further, a good unit test should be fast to ensure it doesn't hinder the development process. This often requires mocking all unit test dependencies. One possible exception to this rule may be for ORM-heavy applications where launching a database in memory might be acceptable.

The unit test's title should clearly articulate its purpose. I advocate for the testWhenShould naming pattern, but other conventions can also work. The unit test code should be divided into three clear sections: setup, execute, and validate. Here's a representative example:

javaCopy code

test*When*Should* {
   //setup
   dependencyOne = mockDependencyOne.return({...});
   dependencyTwo = mockDependencyTwo.return({...});
   objectToBeTested = new ObjectToBeTested(dependencyOne, dependencyTwo);

   //execute
   result = objectToBeTested.someFunc();

   //validate
   assertEquals(result, expectedResult);
}

The Importance of Elegant Unit Test Code

Just like product code, unit test code should adhere to the guidelines of elegance. It should be readable, sectionable, and effortlessly extensible. Elegance in code is often subjective and hard to pin down, as pointed out by Robert Martin in his book "Clean Code" where he dedicated an entire chapter to the subject.

However, no matter how you define elegance, it is crucial to remember that unit test code is as essential as product code and should be treated with equal importance and care.

Fixing Bugs and Updating Tests

Finally, whenever you're resolving a bug, make sure to evaluate why existing unit tests didn't uncover it. Use this as an opportunity to update your tests accordingly. This practice helps prevent regressions, ensures the fix's accuracy, increases code coverage, and boosts the reliability of your test suite.

Adhering to these best practices for unit testing will pave the way for robust software, reliable releases, and ultimately, startup success.