Unit Testing is a type of software testing where individual units or components of the software are tested. The purpose is to validate that each unit of the software code performs as expected. Unit Testing is done during the development (coding phase) of an application by the developers.
Obviously, yes. But, some developers think that Unit Testing sounds easy that than doing it. However, I can say that Unit Testing is easy as it sounds as long you write a good Unit Test and a testable code.
Unit Testing in simple word
In simple words, Unit Testing is a method that instantiates a small portion of our application and verifies its behavior independently from other parts. A typical unit test contains 3 phases:
- First, it initializes a small piece of an application it wants to test (also known as the system under test, or SUT)
- Then, it applies some stimulus to the system under test (usually by calling a method on it),
- Finally, it observes the resulting behavior. If the observed behavior is consistent with the expectations, the unit test passes, otherwise, it fails, indicating that there is a problem somewhere in the system under test.
These three unit test phases are also known as Arrange, Act, and Assert, or simply AAA.
Principles of a Good Unit Test
- Easy to write
Developers typically write lots of unit tests to cover different cases and aspects of the application’s behavior, so it should be easy to code all of those test routines without enormous effort.
The intent of a unit test should be clear. A good unit test tells a story about some behavioral aspect of our application, so it should be easy to understand which scenario is being tested and — if the test fails — easy to detect how to address the problem. With a good unit test, we can fix a bug without actually debugging the code!
Unit tests should fail only if there’s a bug in the system under test. That seems pretty obvious, but programmers often run into an issue when their tests fail even when no bugs were introduced. For example, tests may pass when running one-by-one, but fail when running the whole test suite, or pass on our development machine and fail on the continuous integration server. These situations are indicative of a design flaw. Good unit tests should be reproducible and independent from external factors such as the environment or running order.
Developers write unit tests so they can repeatedly run them and check that no bugs have been introduced. If unit tests are slow, developers are more likely to skip running them on their own machines. One slow test won’t make a significant difference; add one thousand more and we’re surely stuck waiting for a while. Slow unit tests may also indicate that either the system under test or the test itself, interacts with external systems, making it environment-dependent.
- Truly unit, not integration
Unit and Integration tests have different purposes. Both the unit test and the system under test should not access the network resources, databases, file system, etc., to eliminate the influence of external factors.
How to write testable code?
A testable code should have the following criteria:
- A SUT must be loosely coupled to the concrete implementation
- A SUT must follow the Single Responsibility Principle.
- A SUT must not have hidden dependencies.
- A SUT must not have non-deterministic behavior or logic
- A SUT must not have static methods
- A SUT must be easy to understand and maintain.
Click here for a well-explained example
- It’s easy to learn.
- It requires zero setups.
- Managing large test cases is relatively easy because of a snapshot capturing feature.