D
D
Denis2021-01-11 15:37:54
Unit testing
Denis, 2021-01-11 15:37:54

How to do functional testing in Laravel?

Hello. There are many examples on the Internet of how to conduct functional testing. I learned the basic methods and learned how to apply, write tests. Everything goes as I expected and all is well. But now the question arises: what area of ​​routes should tests cover?
Let's start with POST requests. My project (browser online text game) cannot exist without the initial data in the database, so one of the main and first tests is to check that all the initial (base) tables are filled in as they should, for this I use SeederTest:

public function completeness()
    {
        $this->assertDatabaseCount('base_items', base_items::getCount());
    }

Where base_items is the name of the seeder (maybe it's better to change the name).

I plan to conduct POST tests like this: (Am I doing it right??)

public function SuccessReg()
    {
        $this->get('/');
        $response = $this->post(route('register'), ['login' => 'user', 'password' => '123', 'password_confirmation' => '123']);
        $this->assertAuthenticated();
        $this->assertDatabaseHas('users', ['login' => 'user']);
        $response->assertLocation('/home');
    }

    /** @test */
    public function InvalidLogin()
    {
        $this->get('/');
        $response = $this->post(route('register'), ['login' => '', 'password' => '123', 'password_confirmation' => '123']);
        $this->assertGuest();
        $this->assertDatabaseMissing('users', ['login' => '']);
        $response->assertLocation('/');
    }

But it's not so important, because I get what I want. The main question is, is it necessary to test GET requests? That is, elementary controllers, in which I must be sure that they will return the desired view with the desired data set at the desired address and return 200. Something like this:
public function test_home_page()
    {
        \Auth::login(User::factory()->create());
        $response = $this->get('/home');
        $response->assertViewIs('auth.home');
        $response->assertViewHasAll(['me', 'buildings']);
        
        $response->assertStatus(200);
    }

Am I checking everything correctly? If somewhere when passing data to the view an error occurs (something from the database is not found), will there be an error here as well? Does this check of routes guarantee that all pages will open correctly? Another question, is there a way to log in the user to the entire test class at once so as not to register login every time? All that I have demonstrated is the whole point of functional tests, isn't it? Simulate data and behavior, check if the data in the database has changed correctly (I still lack a method to check if the data has changed from specific to specific).
I hope not too many questions, this is my first post on Habré =)

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
sdo, 2021-01-11
@sdo

Am I checking everything correctly?

Try to poke around the code coverage with tests and this will partially answer the question "Is it all right?" But about the right thing - only the one who has accumulated bumps in this project and understands which part of the head should be covered with tests from falling bumps can answer, and which one should be left so that you can see where to go)
If somewhere when passing data to the view an error occurs (something from the database is not found), will there be an error here as well?

Again, it depends on the implementation. If the error is not 200-status, then the test will reveal it. Another thing is that it’s inconvenient to understand - with a failed status test - what exactly happened, so I messed up a method that first checks the status with a condition, if actual_status is not equal to expected_status, then it outputs the response body to the console, and only then assert and falls as it should .
Another question, is there a way to log in the user to the entire test class at once so as not to register login every time?

Rather not, because from test to test - actions are atomic even within the same test-class, these are different transactions (if they are involved). But you can look in the direction of the dependence of the methods of the test, if you want more sugar.
All that I have demonstrated is the whole point of functional tests, isn't it?

I will not undertake to answer, but who requires the whole essence of you? Some aspects of the tests are revealed only by going deeper into the forest.

J
jazzus, 2021-01-12
@jazzus

Why is there no letter Y on the green button on top?) Because the Toaster asks ONE specific question. And not 15. I will write in general. I write tests before development, so the question of choosing a "coverage" is not worth it. I recommend this option. Yes, you write more code, but the development time is shorter as a result. development is a constant debugging of code and logic, which, without tests, needs to be done by hand. Plus, the quality / safety of the code and tests is much higher, there is a detailed well-thought-out technical specification (in tests), documentation and a free head. According to the structure, I first write setUp where I set the necessary data, create objects, etc., and then tests. Duplicate code within the class I take out in methods. Within all tests - in TestCase or traits. Each test (script) starts the logic from scratch, but sometimes I link it via @depends.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question