Generators
Generators copied to clipboard
[Feature Request] ability to generate basic tests for a CrudController
@eduardoarandah has made progress in this regard. Let's move the conversation here instead of email please.
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);
}
}
Talking with @tabacitu , we were wondering:
-
If it's a good idea to abstract common operations in a test (like in a trait)
-
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:
-
I like my tests to be concrete, without abstractions, and check behaviour more than code correctness (For that there's static analyzers like Psalm)
-
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
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
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
btw, my test is a quick-n-dirty one, maybe it's better to:
-
Create the model in
setUpmethod so we can CRUD it -
Disable authentication middleware so we don't have to use
->actingAs(via lluminate\Foundation\Testing\WithoutMiddleware)
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...
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
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
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
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