
Poznati je citat Jamesa Grenninga, jednog od pionira u TDD i Agile razvojnim metodologijama:
Ako se ne bavite razvojem temeljenim na testovima, radite razvoj koji se kasnije ispravlja - James GrenningDanas idemo na Laravelovo putovanje vođeno testovima. Stvorit ćemo Laravel REST API zajedno s autentifikacijom i CRUD funkcionalnošću bez otvaranja Poštara ili preglednika. ?
Napomena: Ovo uputstvo pretpostavlja da razumijete osnovne koncepte Laravela i PHPUnit-a. Ako ste to maknuli s puta? Vozimo se.Postavljanje projekta
Započnite s izradom novog projekta Laravel sa composer create-project --prefer-dist laravel/laravel tdd-journey
.
Dalje, moramo pokrenuti skener za provjeru autentičnosti koji bismo koristili, samo naprijed i php artisan make:auth
tada pokrenite php artisan migrate
.
Zapravo nećemo koristiti generirane rute i poglede. Za ovaj bismo projekt koristili jwt-auth. Dakle, samo naprijed i postavite ga u svojoj aplikaciji.
Napomena: Ako imate pogreške sgenerate
naredbom JWT-
a, možete slijediti ovaj popravak dok ne bude dodan stabilnom izdanju.
Konačno, možete izbrisati ExampleTest
u oba tests/Unit
i tests/Feature
mape tako da se ne ometa naše rezultate testa, a mi smo dobro ide.
Pisanje koda
- Započnite postavljanjem vaše
auth
konfiguracije da koristi JWT upravljački program kao zadani:
Zatim u routes/api.php
datoteku dodajte sljedeće :
2. Sad kad smo postavili upravljački program, postavite svoj korisnički model na isti način:
Ono što smo učinili je da smo upravo implementirali JWTSubject
i dodali potrebne metode.
3. Dalje, moramo dodati naše metode provjere autentičnosti u kontroler.
Pokrenite php artisan make:controller AuthController
i dodajte sljedeće metode:
Ovaj je korak prilično naprijed, sve što radimo je dodavanje metoda authenticate
i register
metoda na naš kontroler. U authenticate
metodi provjeravamo ulaz, pokušavamo se prijaviti i vraćamo token ako je uspješan. U metodi registra provjeravamo ulaz, stvaramo novog korisnika s ulazom i generiramo token za korisnika na temelju toga.
4. Dalje, na dobar dio. Testiranje onoga što smo upravo napisali. Generirajte ispitne satove pomoću php artisan make:test AuthTest
. U novo tests/Feature/AuthTest
dodajte ove metode:
Komentari u gornjem kodu prilično opisuju kod. Jedna stvar koju biste trebali primijetiti je kako stvaramo i brišemo korisnika u svakom testu. Cjelokupna poanta testova je da bi oni trebali biti neovisni jedni o drugima i idealno bi trebali biti u bazi podataka.
Sada pokrenite $vendor/bin/phpunit
ili $ phpunit
ako ga imate globalno instaliran. Trčanje koje bi vam trebalo dati uspješne tvrdnje. Ako to nije bio slučaj, možete pregledati zapisnike, popraviti i ponovo testirati. Ovo je prekrasan ciklus TDD-a.
5. Sad kad imamo provjeru autentičnosti, dodajmo stavku za CRUD. Za ovaj ćemo vodič koristiti recepte za hranu kao svoje CRUD predmete, jer, zašto ne?
Započnite s izradom naše migracije php artisan make:migration create_recipes_table
i dodajte sljedeće:
Zatim pokrenite migraciju. Sada dodajte model pomoću php artisan make:model Recipe
i dodajte ovo našem modelu.
Zatim dodajte ovu metodu u user
model.
6. Sada su nam potrebne krajnje točke za upravljanje našim receptima. Prvo ćemo stvoriti kontroler php artisan make:controller RecipeController
. Zatim uredite routes/api.php
datoteku i dodajte create
krajnju točku.
U kontroler dodajte i metodu stvaranja
Generirajte test značajki pomoću php artisan make:test RecipeTest
i uredite sadržaj kao u nastavku:
Kôd je prilično objašnjen. Sve što radimo je stvoriti metodu koja obrađuje registraciju korisnika i generacije tokena, a zatim koristimo taj token u testCreate()
metodi. Imajte na umu upotrebu RefreshDatabase
osobine, osobina je Laravelov prikladan način resetiranja baze podataka nakon svakog testa, što je savršeno za naš izvrstan mali projekt.
U redu, za sada sve što želimo potvrditi je status odgovora, samo naprijed i pokrenite se $ vendor/bin/phpunit
.
Ako sve bude u redu, trebali biste primiti pogrešku. ?
There was 1 failure:
1) Tests\Feature\RecipeTest::testCreateExpected status code 200 but received 500.Failed asserting that false is true.
/home/user/sites/tdd-journey/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:133/home/user/sites/tdd-journey/tests/Feature/RecipeTest.php:49
FAILURES!Tests: 3, Assertions: 5, Failures: 1.
Gledajući log datoteke, možemo vidjeti krivac je publisher
i recipes
odnos u Recipe
i User
klasama. Laravel pokušava pronaći user_id
stupac u tablici i koristiti ga kao strani ključ, ali u našoj migraciji postavili smo publisher_id
strani ključ. Sada prilagodite linije kao ispod:
//Recipe filepublic function publisher(){ return $this->belongsTo(User::class,'publisher_id');}
//User filepublic function recipes(){ return $this->hasMany(Recipe::class,'publisher_id');}
A zatim ponovo pokrenite test. Ako sve bude u redu, dobit ćemo sve zelene testove! ?
... 3 / 3 (100%)
...
OK (3 tests, 5 assertions)
Sada još trebamo testirati stvaranje recepta. Da bismo to učinili, možemo utvrditi broj recepata korisnika. Ažurirajte svoju testCreate
metodu kao u nastavku:
Sada možemo nastaviti i ispuniti ostatak naših metoda. Vrijeme je za neke promjene. Prvo, našaroutes/api.php
Dalje, dodajemo metode u kontroler. Ažurirajte svoju RecipeController
nastavu na ovaj način.
Kôd i komentari već dobro objašnjavaju logiku.
Lastly our test/Feature/RecipeTest
Other than the additional test, the only other difference was adding a class-wide user file. That way, the authenticate
method not only generates a token, but it sets the user file for subsequent operations.
Now run $ vendor/bin/phpunit
and you should have all green tests if done correctly.
Conclusion
Hopefully, this gave you an insight into how TDD works in Laravel. It is definitely a much wider concept than this, one that is not bound to a specific method.
Though this method of development may seem longer than the usual debug laterprocedure, it’s perfect for catching errors early on in your code. Though there are cases where a non-TDD approach is more useful, it’s still a solid skill and habit to get used to.
The entire code for this walkthrough is available on Github here. Feel free to play around with it.
Cheers!