Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] ability to generate basic tests for a CrudController #109

Open
tabacitu opened this issue Feb 8, 2021 · 10 comments
Open

Comments

@tabacitu
Copy link
Member

tabacitu commented Feb 8, 2021

@eduardoarandah has made progress in this regard. Let's move the conversation here instead of email please.

@eduardoarandah
Copy link

eduardoarandah commented Feb 8, 2021

Here's a test class that I made to test Backpack CRUD operations.

  • refreshes database
  • creates some admin user
  • makes an http request to backpack routes
  • checks the operation works via http code

I made it work via factories, like this one: https://paste.rs/G1N.php7

<?php

namespace Tests\Feature;

use App\Models\EyesColor;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class EyesColorCRUDTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        $this->seed();
        $user = factory(User::class)->create();
        $user->assignRole("admin");
        $this->actingAs($user);
    }

    public function testIndex()
    {
        $this->get(route("eyescolor.index"))->assertStatus(200);
    }

    public function testEdit()
    {
        $this->get(route("eyescolor.edit", 4))->assertStatus(200);
    }

    public function testUpdate()
    {
        $eyescolor = factory(EyesColor::class)->make();
        $this->put(
            route("eyescolor.update", 4),
            $eyescolor->toArray()
        )->assertStatus(302);
    }

    public function testCreate()
    {
        $this->get(route("eyescolor.create", 4))->assertStatus(200);
    }

    public function testStore()
    {
        $eyescolor = factory(EyesColor::class)->make();
        $this->post(route("eyescolor.store", $eyescolor))->assertStatus(302);
    }

    public function testDelete()
    {
        $eyescolor = factory(EyesColor::class)->create();
        $this->delete(route("eyescolor.destroy", $eyescolor->id))->assertStatus(
            200
        );
    }

    public function testShow()
    {
        $eyescolor = factory(EyesColor::class)->create();
        $this->get(route("eyescolor.show", $eyescolor->id))->assertStatus(200);
    }

    public function testSearch()
    {
        $eyescolor = factory(EyesColor::class)->create();
        $this->post(
            route("eyescolor.search", ["search[value]" => $eyescolor->id])
        )->assertStatus(200);
    }
}

@eduardoarandah
Copy link

eduardoarandah commented Feb 8, 2021

Talking with @tabacitu , we were wondering:

  1. If it's a good idea to abstract common operations in a test (like in a trait)

  2. What strategy should we use for testing (my example checks only http response)

Testing seems like a polarizing subject,

My preference is on the pragmatic side:

  1. I like my tests to be concrete, without abstractions, and check behaviour more than code correctness (For that there's static analyzers like Psalm)

  2. I would like to test the surface that joins backpack with user code.

What's that surface? I guess:

  • http request works? create, update, delete, search
  • fields correctness (does the file view render? does it show a non-empty?)
  • is there a JS error in browser console while rendering create/list/show/update forms?

And for code that backpack generates:

Something like:

backpack:create factory --model user --test

@pxpm
Copy link
Contributor

pxpm commented Feb 8, 2021

Hello @eduardoarandah . I myself had did some dig about the subject.

I have been studying about Puppetter https://pptr.dev/ to test actual expected behaviour from the whole Crud in browser, like notifications, table sortings, fields etc etc.

I'v did some small projects with it, not backpack related, but still .. I am impressed in how easy is to spin up a browser, control it programatically and assert vs a lot of common stuff that we keep repeating everytime we want to do, even if the smallest code change.

I think that testing request status is kind (notice kind here) of same as asserting with crud functions. If the request fail is probably because you used wrong input data, the same will happen if you input wrong data on functional testing. They may be complementary in some scenarios though.

More tests means less bugs, I am in for it.

Best,
Pedro

@eduardoarandah
Copy link

Hello @eduardoarandah . I myself had did some dig about the subject.

I have been studying about Puppetter https://pptr.dev/ to test actual expected behaviour from the whole Crud in browser, like notifications, table sortings, fields etc etc.

I'v did some small projects with it, not backpack related, but still .. I am impressed in how easy is to spin up a browser, control it programatically and assert vs a lot of common stuff that we keep repeating everytime we want to do, even if the smallest code change.

I think that testing request status is kind (notice kind here) of same as asserting with crud functions. If the request fail is probably because you used wrong input data, the same will happen if you input wrong data on functional testing. They may be complementary in some scenarios though.

More tests means less bugs, I am in for it.

Best,
Pedro

Do you think it has an advantage above official tool laravel dusk assertSee ?

https://laravel.com/docs/8.x/dusk#creating-multiple-browsers

@eduardoarandah
Copy link

btw, my test is a quick-n-dirty one, maybe it's better to:

  • Create the model in setUp method so we can CRUD it

  • Disable authentication middleware so we don't have to use ->actingAs (via lluminate\Foundation\Testing\WithoutMiddleware)

@tabacitu
Copy link
Member Author

tabacitu commented Feb 9, 2021

I would also lean towards Dusk rather than Pupeteer (in principle) because I expect most developers to prefer continuing the tests if they are written in Dusk. Then again if puppeteer has something dusk doesn't... yeah totally.


is there a JS error in browser console while rendering create/list/show/update forms?

We can do that?! I think checking that the page loads and that is there are no JavaScript console errors... that would be a great minimum test to start with...


One reason I like testing for 200 return is that because of our convenient controllers, if you create a custom operation and you mess up the Route definition function, this would not only break the CrudControllers that use that particular operation, but also all other controllers - including app. So having these minimal tests that show the pages loading would at least be reducing the chance that the developer breaks the entire app by doing something in backpack. of course that's only if they actually run the tests... so yeah...

@pxpm
Copy link
Contributor

pxpm commented Feb 9, 2021

100% agree!

I am not totally aware of the capabilities of Dusk, but what I enjoyed more in Pupeteer was the fact that it can handle javascript very well.

I'm don't even have more than the basic knowledge to try to sell pup. over dusk. I can only say that pup. handles multiple browser tabs very well (so writting small tests and running them at once), async requests etc, is 100% integrated into chrome browser, so yeah, it can be used to load test your server using dev tools (chrome) performance metrics. It's a new world for me.

What I don't like is the fact the is only for chrome, and is in JS.

I don't know how dusk handles it, if it's easier I would have been missing in dusk here.

Probably dusk makes more sense here, since it has direct capabilities related to laravel stuff, like mocking events/jobs and stuff and .. is PHP!

From small research:

$this->assertEmpty($browser->driver->manage()->getLog('browser')); returns an array of browser error logs, except console.log

Best,
Pedro

@stale
Copy link

stale bot commented Jun 26, 2021

Hi there!

Is this still an issue? No activity in 60 days. I'm going to mark it as stale for now, and close it in 14 days if no further activity occurs. I know you guys are all busy, but if this is important to you please reply or something, so I know not to close it.

Thank you!

--
Justin Case
The Backpack Robot

@stale stale bot added the stale label Jun 26, 2021
@tabacitu tabacitu removed the stale label Jun 28, 2021
@stale
Copy link

stale bot commented Nov 28, 2021

Hi there!

Is this still an issue? No activity in 60 days. I'm going to mark it as stale for now, and close it in 14 days if no further activity occurs. I know you guys are all busy, but if this is important to you please reply or something, so I know not to close it.

Thank you!

--
Justin Case
The Backpack Robot

Copy link

stale bot commented Feb 11, 2024

Hi there!

Is this still an issue? No activity in 60 days. I'm going to mark it as stale for now, and close it in 14 days if no further activity occurs. I know you guys are all busy, but if this is important to you please reply or something, so I know not to close it.

Thank you!

--
Justin Case
The Backpack Robot

@stale stale bot added the stale label Feb 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

No branches or pull requests

3 participants