With merits to João Batista Neto - Web Developer at Imaster
Okay, your question is about unit tests in general. You obviously didn’t understand the intention or the motivation to write tests.
Unit testing is intended to verify that the written algorithm is working according to your requirements. The developer is responsible for the code he writes. In order to be responsible, the developer tests his code to ensure it works. The motivation is precisely this: Ensure your responsibility on the written code.
The focus of Phpunit, Junit, or any unit test framework, is not to check for feedback. It is to check the functioning of the entire algorithm.
When we talk about object orientation, it is common to talk about SRP - the principle of sole responsibility. If you understand this principle, then it is easy to understand unity. Unity is precisely a responsibility. Each participant of its application who has a specific responsibility is, by definition, a unit of the application.
When you go to write a unit test, you will test that specific unit. Therefore, you must isolate its dependencies. And you must isolate them, as it is not the responsibility of the unit being tested, test other units.
In addition, there are some specific principles for testing from the point of view of TDD. These are the principles F.I.R.S.T.
F = Tests need to be run quickly. I will not go into detail about this principle as it falls outside the scope of the thread.
I = Tests need to be isolated. Here we enter one of the points you touched on. HTTP databases, requests and responses. Whenever you work with things outside your code, you run a risk of these things affecting code behavior temporarily.
What broke? It was the code, or the link that fell?
To prevent external things from affecting code operation, you encapsulate such external things as the HTTP protocol and databases into Mockups. Mocks act as ideal scenarios for the functioning of what is external.
This encapsulation is important, as you are testing the algorithm that sends a request or handles a response, so there is no reason why you should be affected by a connection problem.
R = Tests must be repeatable at any time and in any order. This principle is also affected by databases. For example, imagine that you have a base with a primary key X. If you write the test that will get information from the base, you will need to have that information at the base, ie you will need to record it before.
If your achievement test depends on the recording test taking place before, then you have a design problem in your test, as you will not be able to change the order of the tests. Again, this is why we create database mocks. Because it is irrelevant to the algorithm whether the information is actually at the base, or whether there is even a base. You are not testing the base. She already has her own tests.
You need to test YOUR code. Anything outside it, is outside the scope of the unit test.
S = The tests need to be able to be performed without any human intervention. The purpose of this is to effectively automate the tests. If every time you go to test, you need to navigate the application, you might stop testing it. Imagine a great application, hundreds or thousands of pages long. If you need to navigate page by page, you won’t be able to test your code and eventually give up testing.
T = The tests need to be written BEFORE the code that will pass them. Nor will I go into detail about this principle because it falls outside the scope of the thread.
The point is that anything other than YOUR code specifically must be encapsulated and isolated. Unit tests are concerned with testing only the code you wrote. If you focus exclusively on your code and encapsulate everything external, all your issues will be resolved at the same time.
And if you understand everything I’ve written in the above, you’ll also understand why we say TDD is a design validator.
See, we have to send an HTTP request and then handle the response. How many responsibilities there are in this process?
1 - Opening of the connection.
2 - Connection status check.
3 - Sending the request.
4 - Check the success of sending the request.
5 - Reading the answer.
6 - Verification of the success of the reading of the answer.
7 - Treatment of the response.
A simple submission of an HTTP request has at least 7 different responsibilities. All these responsibilities require specific testing.
When you work your tests focusing on the unit’s proposal, you will forcibly end up better defining the responsibilities of your code and will have a better design as a whole.
Functions as
call('POST/GET', 'someRoute')
are specific to the Larable and are not part of phpunit. Unit tests are limited to testing classes alone, and the methods listed fit more like integration tests. Also try to ask separate questions. Four questions in the same topic is not feasible for any objective answer. If you want to ask conceptual questions of tests you can resort to this reply– gmsantos