Unit tests work as an initial quality control and code effectiveness. Through them, we can validate how the code unit works and whether it does it correctly or not. The tests seek to force a behavior in the code to analyze its responses and internal functioning.
When we think of unit tests, we think of each case separately; with this I mean that we think of each test as unique and independent. Imagine that we are the professors of a classroom and that each question in an exam is a case; from the first question, such as: “What is your name?”, to the most complex, such as: “Define the steps to follow in case of being approached by a Martian heavy on Coca-Cola”. Alluding to the questions, the first is one simple; the code / person will say his name. But in the last one it is very probable that both subjects to be evaluated will be dismayed to say the least.
The unit tests that we think of as questions of an exam, are then concrete questions and, in most cases, they must be atomic and then integrated in a single execution; “What are you? What do you give? How do you give it? “
We must know that performing Unit Tests is 50% code knowledge and 50% destructive creativity. I say this because we must consider all the other ways in which the system / code shouldn’t work in order to see how it reacts and, if necessary, modify the code to adapt it to pass the test.
- Dimensioned errors: the unit tests allow you to know where your code zone fails or what prevents its expected behavior and therefore helps to locate errors more easily.
- They are part of the code documentation.
- Simplify integration: If the parts to be integrated have already been tested individually, you should only invest effort in the integration and integration tests.
- They approve the change: they are an excellent tool for developers to positively change the code, improving its operation.
When people asks me how the unit tests are, I usually respond that they are ACRI. This means:
Atomic and Automatable: Small and directed to a specific point of the code that should not require a manual intervention for its execution.
Complete: Covers as much of the code as possible.
Reusable: must support the DRY (Don’t Repeat Yourself) approach, even between projects.
Independent: Although they can be executed in chains, each one must be able to be executed separately.
Most of the time, when we perform Unit Tests, we analyze the exceptions they give out. The Unit Testing work, in addition to looking for a correct answer, aims to find inconsistencies and errors that can or should work in a program. We could say that Unit Tests are 70% the search and control of exceptions of a system or code, which makes these two the fields to which we must assign greater importance. Many times when performing unit tests on a new project the exceptions are scarce and, in the vast majority, controlled. But as the project grows and new lines, methods or classes are added more and more exceptions appear. Therefore, you must reorganize or edit the Tests that take give errors and compare them against what your main goal should be.
To explain this in a better way, let’s think of an algorithm that should yield the sum of two integers. We pass two integers into the algorithm and, knowing that the answer is correct, then the addition algorithm is correct. but, what would happen if you were to overload it with two strings or numeric type objects, but not of the integer type? In any of these cases it will inevitably fail, and the question arises: should we capture the error and allow it to happen or refactor the code so that it tries to transform the values assigned to the type that is handled in the method? Either of these two options are valid. However, it is vital to modify the Test and, in the case of the code, refactoring is essential.
A test model to this module as an example would be something like:
- Used the method with two integers.
- Used the method with an integer and a string.
- Used the method with two strings.
- Used the method with two floating values.
- Used the method and did not overload the parameters.
In cases 2 and 3 it must show error, but it is valid that the code tries to transform the values that come in “string” to numeric in case the “string” is a number such as “3” instead of a 3.
. . .
The use of Unit Tests is a practice that help programmers generate trust and quality code. In my experience, it is an excellent way to experiment and increase efficiency in a language in which you already have a level above average, expanding your comfort zone within that language. If they are run in a systematic way, they help identify unexpected code conflicts that escape our sight, helping to work as a team and promoting the effectiveness of other practices such as GIT Workflow.
For inquiries about our development and design services, e-mail us firstname.lastname@example.org.