Doubts about unitary tests

Asked

Viewed 668 times

4

I am new to unitary testing and am in doubt in some basic applications.

First: the focus of phpunit is to check if a return has an expected pattern. If yes, the test has passed. If not, it throws error. However, whenever I use the call('POST/GET', 'someRoute'), when running the tests, I get the html result in the console. Instead of just a check. To get better, I put a assertResponseOk() after the call(). But phpunit says there is no http status of this test.

Second: My application uses Reposories for database persistence. The application works perfectly. But whenever I run a test, it tells me that the Positorios cannot be instantiated. What is the difference in the behavior of phpunit for the server of the Laravel in this case?

Third: (have patience with this one) All the tutorials on unitary tests say: "isolate dependencies". After all, what does that mean?

Fourth: About methods in controllers that already deliver information in the view. The View::make() (data delivery from a method to a view in the Lockbox) always have to stay in a separate mode? Type: one method to assemble a calendar collection and another to pick up the agenda collection and deliver to a view. What if a view needs a lot of data? Do I also test this method? Or not because all your data has been previously assembled and tested?

I thank those who can help me with any kind of information. I’ve read several tutorials, but as Jeffrey Way himself says: "testing controllers is not one of the easiest tasks"

  • 2

    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

2 answers

3

As you have put many things into a question it is just not clear your level of understanding of unit tests. Okay, in the end I understood that you want to test the controllers, but before that, you already work with unit tests? Already started/managed to use with simpler things?

Often the problem is the lack of focus on object orientation. If you haven’t been able to use it yet, I suggest you start testing services. Whatever business rule, you move to new service classes and test the return of these classes. If you didn’t do this, it’s a good start. If you have already done it, then it remains to be seen what the expected purpose of the tests with the controllers and the repositories is. Because in the case of the repository, if you’re just testing that the model is persisting, it doesn’t make sense, because you’re testing the eloquent and we know it works. Just an example.

As for isolating dependencies, a classic example, your system relies on a database. But in unit testing, the ideal is for you to use some Mock Object that abstracts the database and "isolates the dependency" of the database.

0


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.

  • 3

    Where exactly do you answer the questions raised in the question?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.