Introduction to Unit Testing
How confident are you in your code? Are you certain the code you deploy won’t introduce bugs in your system’s production environment?
If those questions make you hesitate or feel anxious, you might need to apply unit testing to your code.
What Is Unit Testing
Unit testing is the practice of testing the individual units that make up the entirety of your software code. Tests are carried out to verify that each unit behaves as expected under various conditions. Simply put, it ensures that for every input, the output produced matches expectations.
![Ilustrasi Unit Test terhadap Fungsi tambah(../../../assets/unit-test.png)
Illustration of a Unit Test against the tambah(a,b) function
The definition of what constitutes a unit is not prescribed in a fixed way. It can be as specific as a single function, or as broad as an interface or a class in object-oriented programming. Simply put, a unit can be thought of as the smallest component that can be tested in isolation within our program.
Such testing is not carried out by humans as in manual testing, but is automated by a test suite program guided by specifications written by the developer. So when we adopt unit testing, we don’t just need to write our software code — we also need to write the unit testing specifications.
Why Do We Do Unit Testing?
Unit testing is done to ensure that the independent units of our code behave according to specification, and to detect potential bugs in our code before that code enters and runs in production. Additionally, unit testing can ensure that refactoring, adding new features, or modifying implementation details of already-running features won’t introduce bugs.
Test-driven Development (TDD)
Unit testing is one of the elements that enables us to practice TDD, or test-driven development. TDD is a software development method that begins by translating requirements into test cases, which are then translated into code. This method ensures that the code we write, beyond being protected by unit tests, also aligns with the scope defined in the requirements.
In practice with unit tests, TDD is carried out by writing the unit test specification code first. The specifications are written directly based on the product specifications set out in the requirements. When run, all the written tests will inevitably fail. From there, the developer gets to work writing the program so that all the written test cases pass.
This method is claimed to have many advantages. First, the code produced will have high coverage (the proportion of code ‘protected’ by unit tests), potentially even reaching 100%. Additionally, according to one study, developers who write more unit tests tend to be more productive [1], and implementing TDD means writing more unit tests.
Unit Testing as Documentation
Writing unit tests means writing specifications for the units in our program: what those units can do, and what they cannot do. The unit test specifications automatically become documentation about the program itself.
For example, taking the unit function tambah(a,b), we could define the following test cases:
- The function correctly adds two values of type number
- The function will throw a
TypeErrorif one of its parameters is not of type number - The function accepts both negative and positive number parameters
Simply by reading those test cases, another developer does not need to read the implementation inside the function to understand what it does.
Although adopting unit testing may feel like a heavy lift at first, in the end unit testing will bring benefits that far outweigh the costs. For me, unit testing can also serve as a good starting point for exploring broader software testing methods such as integration testing and end-to-end testing. If you haven’t started yet — now is the time!