What is unit testing?
Unit testing is a type of software testing where individual units or components of a software are tested. The purpose is to validate that each unit of the software code performs as expected.
Why to use unit tests?
The most important advantage, which I can think of is that unit tests are making our work faster and less buggy. Imagine that you have done some code-refactoring. It is enough to run unit tests to have approximate feedback about the success of our changes. In case of new future, the unit tests can help with finding bugs early.
How to write high-quality unit tests?
To wirte high-quality unit tests it is recommended to follow FIRST rules, which are:
F (fast) – unit tests should be fast, not to make developers tired of executing them.
I (isolated) – unit test should test only small and single piece of code.
R (repeatable) – unit test result should always be the same and not related to other tests or outside world.
S (self-validating) – unit tests should be started automatically.
T (timely) – unit test should be added/updated just before/after code adding/refactoring.
What scope does „unit” exactly mean?
A unit may be an individual function, method, procedure, module or object. This kind of test should never be confused with integration test, which are responsible for testing how different pieces of the system work together.
What to look for when writing unit tests?
Unit test should cover happy path, exception cases and also boundary conditions.
Boundary conditions might be hard to notice and due to that easy to omit. High-quality unit tests are covering all scenarios, following CORRECT rules might help with that.
C (conformance) – unit test ensures that a tested software meets a defined set of standards e.g. before saving e-mail it should be valdiated.
O (ordering) – unit test should check behaviour of unit with different set of data e.g. with ordered and unordered data.
R (range) – unit test should check what will happen when passing minimum/maximum values and also invalid value to unit e.g. passing -1 as a person age.
R (reference) – all prerequisites before starting a test are met e.g. log history should be shown only for logged user.
E (existance) – unit test should check what will happen when passing NULL or 0 value to unit.
C (cardinality) – unit test should check size of unit result e.g. after cancelling a shoping cart, a cart should be empty.
T (time) – unit tests should check if everything is executed in order e.g. restoring a backup before creating it. This point is also really important in multithreading programming, where race-condition may take place.
What is required code coverage?
Code coverage is a software testing metric that determines the number of lines of code that is successfully validated under a test procedure, which in turn, helps in analyzing how comprehensively a software is verified.
Required test coverage is 80%. This number ensures that our code was sufficiently covered by the unit tests. Some may ask why not 100%. Well, generally there are some code-parts which do not require testing e.g. getters and setters.
What must not be forgotten?
Always remember to update unit test related to code change. Unit test which is out-of-date can be misleading for other developers or even for you in near future.