Introduction to Unit Test

In 2015, a defining event completely changed how I think about Testing in the software development lifecycle. It was the first time I had to write a 5 Whys, 9 Steps incident root-cause report. The primary cause of the failure was underestimating Unit Tests, and the consequences were severe. Read on to find out why ;)).

UnitTest

Prior to that, in university, I had learned about Black Box Testing and White Box Testing. I first encountered Unit Testing in practice in 2013 at Global CyberSoft. At that time, leadership largely regarded unit tests as formal “compliance reports”; the actual quality checkpoints relied almost entirely on Code Review and manual QA/Testing. Fortunately, our tech lead and QC team were exceptionally skilled, so overall project quality remained solid.

In 2015, I moved to Mulodo. Another colleague and I took over two projects from departing engineers. Under tight deadlines, sparse documentation, and rushed knowledge transfers, the handover was far from ideal. Consequently, we hit a “monster production bug” during our very second change request. The root cause was a subtle change in a shared utility function that was called across dozens of core features. At first, I assumed the failure was simply due to “missing context” that should have been caught in Code Review. But after a thorough discussion with my Engineering Manager, I realized this failure was 100% preventable if proper Unit Testing had been in place.

So what is Unit Testing and why is it so essential?

What is a Unit Test?

Unit Testing is an integral phase in software development. Ideally, it begins right after Functional Design, precedes Implementation, and finishes alongside code completion, ensuring that the implementation adheres strictly to the architectural specifications. Unit testing is performed by developers and classified as White Box Testing.

A Unit represents a method in object-oriented programming, a function in functional programming, or a procedure in procedural code. Developers identify every logical branch of the unit, constructing a comprehensive suite of input arguments paired with expected outputs (including expected return values and expected exceptions). The test framework executes each case, asserting actual behavior against expected results, and generates actionable test reports.

Why do I have to write Unit Tests?

  • Guarantees code behaves according to design: This safety net becomes even more critical when refactoring or extending legacy logic.
  • Clarifies requirements and guides implementation upfront: Writing unit tests first forces you to think through all possible edge cases and establish inputs/outputs beforehand—much like knowing your exact destination before embarking on a journey ;)).
  • Catches bugs early saves immense engineering time and operational cost.
  • Enforces self-review: Writing tests compels you to critically examine your own code structure ;)).
  • Reduces cognitive burden in Code Reviews: Reviewers can review with higher confidence when changes are proven with robust tests.
  • Detects edge-case defects that high-level Black Box Testing easily overlooks.
  • Essential foundation for CI/CD automation pipelines.

Concepts in Unit Testing

  • Test Case: An individual test scenario covering a specific logic branch of the unit under test, defined by a distinct set of inputs and expected outputs.
  • Assertion: A verification check that confirms actual results match expected outcomes. In JUnit, these include functions such as assertEquals, assertThrows, assertArrayEquals, assertNotNull, assertNull
  • Test Suite: A logical collection of Test Cases, organized by module, package, class, or feature depending on test strategy.
  • Production Code: The core application code compiled and deployed to production servers.
  • Test Code: The testing code that executes test suites during local runs and automated build pipelines; excluded from production bundles. Developers should always run test suites locally before submitting a Merge / Pull Request.

Conclusion

I hope this article demonstrates why Unit Testing is a non-negotiable engineering discipline. There is much more to explore, and I will share advanced testing techniques in upcoming posts. To conclude, I’d like to share a quote from my former Engineering Manager who enlightened me ;)):

Unit Testing is not a developer’s burden—it is a developer’s privilege. It protects us from hidden failures. So write your unit tests with wholehearted dedication.
Tài Nguyễn

Thanks for reading!

updatedupdated2026-09-052026-09-05
Load Comments?