Merhaba,
Bu yazıda Laravel'de Unit Test kullanımından bahsedeceğim. Örnek projede basit bir Rest Api yazıp onun üzerinden gideceğim. Örnek projeyi Github üzerinden paylaştım. İndirip inceleyebilirsiniz.
İlk olarak istediğimiz bir dizinde (ör: masaüstü) komut satırını açıp yeni bir Laravel projesi oluşturmak için gerekli kodları yazıyoruz:
composer create-project --prefer-dist laravel/laravel unit-test-sample
Sonrasında Xampp yardımıyla yerelde bir veritabanı oluşturuyoruz. Proje kök dizinindeki .env dosyasını açarak veritabanı bilgilerini aşağıdaki gibi düzenliyoruz:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=unit_test_sample DB_USERNAME=root DB_PASSWORD=
defaultStringLength hatasıyla karşılaşmamak için app/Providers/AppServiceProvider.php dosyasını açarak boot() fonksiyonunu düzenliyoruz:
public function boot() { Schema::defaultStringLength(191); }
Şimdi bir blog sitemizin olduğunu ve bu sitede yazılar paylaştığımızı düşünelim. Bu yazıların veritabanında tutulduğu tabloyu oluşturmak adına;
php artisan make:migration create_posts_table
şeklinde migration oluşturup up() kısmını;
public function up() { Schema::create('posts', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('title'); $table->text('content'); $table->timestamps(); }); }
şeklinde düzenliyoruz ve tablomuzu oluşturmak için;
php artisan migrate
komutunu çalıştırıyoruz.
Model dosyamızı oluşturuyoruz;
php artisan make:model Post
Post model dosyamızın içeriği;
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { protected $fillable = [ 'title', 'content' ]; }
api.php dosyamızı açıp içeriğine;
Route::group(['prefix' => 'posts'], function () { Route::get('/', 'PostController@index')->name('posts'); Route::get('/{post}', 'PostController@show')->name('posts.show'); Route::post('/', 'PostController@store')->name('posts.store'); Route::put('/{post}', 'PostController@update')->name('posts.update'); Route::delete('/{post}', 'PostController@delete')->name('posts.delete'); });
şeklinde route tanımlamalarını yapıyoruz.
Controller dosyamızı oluşturuyoruz;
php artisan make:controller PostController
PostController dosyamızın içeriği;
<?php namespace App\Http\Controllers; use App\Post; use Illuminate\Http\Request; class PostController extends Controller { public function index() { return Post::all(); } public function show(Post $post) { return $post; } public function store(Request $request) { $post = Post::create($request->all()); return response()->json($post, 201); } public function update(Request $request, Post $post) { $post->update($request->all()); return response()->json($post); } public function delete(Post $post) { $post->delete(); return response()->json(null, 204); } }
Böylelikle Rest Api hazır hale gelmiş oluyor.
Artık işin Unit Test boyutuna geçebiliriz;
ÖNEMLİ NOT: Unit Test sahte (fake) verilerle yapılır. Herhangi bir şekilde gerçek veritabanımıza müdahale etmemesi gerekir ki proje de karmaşıklığa hatta daha da ötesi veritabanımızdaki tabloların tamamen silinmesi gibi durumlara yol açmasın. Bundan dolayı yapmamız gereken işlemler şu şekilde olacaktır;
- Factory dosyası oluşturuyoruz;
php artisan make:factory PostFactory
PostFactory dosyamızın içeriği;
<?php /* @var $factory \Illuminate\Database\Eloquent\Factory */ use App\Post; use Faker\Generator as Faker; $factory->define(Post::class, function (Faker $faker) { return [ 'title' => $faker->sentence, 'content' => $faker->paragraph ]; });
- Yerelde test adında bir veritabanı oluşturuyoruz ve .env dosyamızı açıp içeriğine test veritabanımızı da ekliyoruz;
DB_CONNECTION_SECOND=test DB_HOST_SECOND=127.0.0.1 DB_PORT_SECOND=3306 DB_DATABASE_SECOND=test DB_USERNAME_SECOND=root DB_PASSWORD_SECOND=
- phpunit.xml dosyasını açıp <php> taglarının bulunduğu kısma veritabanı olarak test'i kullanmak istediğimizi belirtiyoruz;
<php> <server name="APP_ENV" value="testing"/> <server name="BCRYPT_ROUNDS" value="4"/> <server name="CACHE_DRIVER" value="array"/> <server name="MAIL_DRIVER" value="array"/> <server name="QUEUE_CONNECTION" value="sync"/> <server name="SESSION_DRIVER" value="array"/> <server name="DB_DATABASE" value="test"/> </php>
- tests klasörünün içindeki TestCase dosyamızı açıp içeriğini şu şekilde düzenliyoruz;
<?php namespace Tests; use Faker\Factory; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { use CreatesApplication, DatabaseMigrations; protected $faker; public function setUp(): void { parent::setUp(); $this->faker = Factory::create(); } }
- test dosyamızı oluşturuyoruz;
php artisan make:test PostTest --unit
PostTest dosyamızın içeriğini şu şekilde düzenliyoruz;
<?php namespace Tests\Unit; use App\Post; use Tests\TestCase; class PostTest extends TestCase { public function test_can_create_post() { $data = [ 'title' => $this->faker->sentence, 'content' => $this->faker->paragraph ]; $this->post(route('posts.store'), $data) ->assertStatus(201) ->assertJson($data); } public function test_can_update_post() { $post = factory(Post::class)->create(); $data = [ 'title' => $this->faker->sentence, 'content' => $this->faker->paragraph ]; $this->put(route('posts.update', $post->id), $data) ->assertStatus(200) ->assertJson($data); } public function test_can_show_post() { $post = factory(Post::class)->create(); $this->get(route('posts.show', $post->id)) ->assertStatus(200); } public function test_can_delete_post() { $post = factory(Post::class)->create(); $this->delete(route('posts.delete', $post->id)) ->assertStatus(204); } public function test_can_list_posts() { $posts = factory(Post::class, 2)->create()->map(function ($post) { return $post->only(['id', 'title', 'content']); }); $this->get(route('posts')) ->assertStatus(200) ->assertJson($posts->toArray()) ->assertJsonStructure([ '*' => [ 'id', 'title', 'content' ] ]); } }
PostTest dosyamızda yazmış olduğumuz kısımları kısaca özetleyecek olursak;
- test_can_create_post kısmında;
- title ve content içeren fake bir veri oluşturduk.
- Rest Api'de yer alan store fonksiyonuna fake veri ile post isteğinde bulunduk.
- Cevap olarak gelen durum kodunu ve json verisini kontrol ettik. Durum kodu 201'e ve json verisi de gönderdiğimiz veriye eşitse testten geçmesini söyledik.
- test_can_update_post kısmında;
- Post modeline uygun fake bir veri oluşturduk.
- Rest Api'de yer alan update fonksiyonuna fake veri ve id parametresi ile put isteğinde bulunduk.
- Cevap olarak gelen durum kodunu ve json verisini kontrol ettik. Durum kodu 200'e ve json verisi de gönderdiğimiz veriye eşitse testten geçmesini söyledik.
- test_can_show_post kısmında;
- Post modeline uygun fake bir veri oluşturduk.
- Rest Api'de yer alan show fonksiyonuna id parametresi ile get isteğinde bulunduk.
- Cevap olarak gelen durum kodunu kontrol ettik. Durum kodu 200'e eşitse testten geçmesini söyledik.
- test_can_delete_post kısmında;
- Post modeline uygun fake bir veri oluşturduk.
- Rest Api'de yer alan delete fonksiyonuna id parametresi ile delete isteğinde bulunduk.
- Cevap olarak gelen durum kodunu kontrol ettik. Durum kodu 204'e eşitse testten geçmesini söyledik.
- test_can_list_posts kısmında;
- Post modeline uygun fake 2 adet veri oluşturduk.
- Rest Api'de yer alan index fonksiyonuna get isteğinde bulunduk.
- Cevap olarak gelen durum kodunu, json verisini ve json verisinin yapısını kontrol ettik. Durum kodu 200'e, json verisi gönderdiğimiz veriye ve json verisinin yapısı belirttiğimiz yapıya eşitse testten geçmesini söyledik.
Son olarak komut satırına şu ifadeyi yazarak testimizi çalıştırıyoruz;
"./vendor/bin/phpunit"
Not: Tırnak işaretlerini (") unutmuyoruz.
Gelen sonuçta kodumuzun tüm testlerden başarılı şekilde geçtiğiniz görebiliriz;
Umarım yararlı olmuştur.
İyi çalışmalar...
Yorumlar 2 yorum yapıldı.
Yeni Yorum