آموزش تست نویسی در لاراول با مثال

تست نویسی در لاراول

چرا در زبان لاراول به تست نویسی نیاز داریم؟

لاراول می گوید تست نویسی کار آسانی است، زیرا این تست ها با انجام دادن بخشی از کدها تمام خطاهای موجود را نمایش می دهند. پس اگر در حال راه اندازی یک ویژگی جدید در برنامه خود هستید می توانید از این روش به عنوان دستیار بررسی کدهای جدید و قدیمی استفاده کنید. آزمایش مجدد همه ویژگی های برنامه، همه هدف ما در این تست نویسی خواهد بود که در ادامه بیشتر با این مبحث آشنا خواهید شد.

پیش نیازهای تست نویسی در Laravel

  • آشنایی اولیه با زبان برنامه نویسی PHP و فریم ورک Laravel
  • نصب کردن Composer بر روی دستگاه
  • نصب و راه اندازی زبان برنامه نویسی PHP در سیستم
  • نصب Git در سیستم
پیشنیازهای تست نویسی در لاراول

نحوه تست نویسی در لاراول با مثال

تست نویسی تحت عنوان “Test Driven Development” که با TDD شناخته می شود، تضمین می کند که کد ما نیازهای نرم افزار مشخص شده را برآورده خواهد کرد. بنابراین مراحل زیر را با دقت اجرا کرده و در صورت بروز ایراد با پشتیبانی فنی ما وارد گفت و گو شوید.

نکته مهم! تست نویسی در لاراول انواع مختلفی دارد، بنابراین این آموزش با در نظر گرفتن کاربران مبتدی و حرفه ای نوشته شده است.

1- راه اندازی اپلیکیشن

مراحل این تست نویسی در یک برنامه تجاری ساخته شده با استفاده از Laravel و Vue است که برای مشاهده آن می توانید به وب سایت Github مراجعه نمایید. توجه کنید که برای انجام مراحل تست زیر باید پروژه را نصب کنید. دستورالعمل های راه اندازی در فایل Readme آورده شده است. (برای ارسال لینک نصب پروژه از طریق کامنت درخواست دهید) 

2- راه اندازی محیط تست

در این مرحله با فرض اطلاع از اینکه لاراول با فایل Phpunit.xml می آید، تنظیمات مربوطه و اجرا کدها از قسمت Phpunit انجام می شود. برای تغییرات دلخواه می توانید از فایل Phpunit وارد شده و یا یک فایل دیگر به عنوان .Env.testing را اجرا کنید. برای یکپارچگی داده ها یک پیکربندی پایگاه داده متفاوت را آزمایش کرده و در قسمت های Session ،Caching Queues ،Email و Third-party tools به اجرا درآورید.
اکنون پایگاه داده متفاوت برای آزمایش (مانند Sqlite) ایجاد کنید. ما در این قسمت ما تصمیم داریم تا فایل جداگانه ای را برای این کار اضافه کنیم. پس برای همراهی با ما فایل .Env.testing را بسازید و کد زیر را وارد کنید:

APP_NAME=Laravel
APP_ENV=testing
APP_KEY=base64:5CpEFQ9UTR543dbJUsT3araoSSyxuN8NF92gCJJXpk8=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/test.sqlite
BROADCAST_DRIVER=log
CACHE_DRIVER=array
SESSION_DRIVER=array
SESSION_LIFETIME=120
QUEUE_DRIVER=sync
MAIL_DRIVER=array

اکنون باید فایل Database/test.sqlite را ایجاد کنید:

 touch database/test.sqlite

به دیتابیس مهاجرت کرده و Seed کنید:

php artisan migrate --seed --env=testing

در این مرحله می توانید با اضافه کردن خط --Env=testing flag به Laravel Artisan دستور استفاده از تنظیمات آزمایشی در فایل .Env.testing را بدهید.

3- راه اندازی تست ها

اکنون در این راهنما می خواهیم تست های خودمان را بنویسیم که در ابتدا لازم است تا هر کلاسی که ایجاد می کنیم یک تست داشته باشد. در واقع تمام آنچه که ما از انجام تست های زیر می خواهیم گرفتن جواب های دقیق در قالب های مناسب بدون صدمه زدن به ویژگی های قبلی برنامه است. به نحوه راه اندازی این تست ها در ادامه اشاره خواهد شد.
نحوه راه اندازی تست ها در لاراول

تست هایی که باید در لاراول انجام دهید!

در تست های زیر تمام تمام نقاط پایانی API برای آزمایش در نظر گرفته شده است که تعدادی از آن ها شامل موارد زیر است: 
  • امکان اجرا، خواندن، به روز رسانی مراحل محصولات و تایید سفارش
  • عدم صدور اجازه برای سفارش محصولات ناموجود
  • امکان تایید سفارش از طرف مدیریت
  • به روز رسانی پلتفرم سفارشات پس از تایید و ارسال

1- تست نقاط پایانی محصول

برای بررسی Product Endpoints که به آزمایش نقاط پایانی محصول نیز شناخته می شود، باید دستور زیر را در ترمینال اجرا کرد تا کلاس تست مورد نظر ما ایجاد شود:

 php artisan make:test ProductTest --unit

در مرحله بعدی باید وارد فایل tests/Unit/ProductTest.php شده و الگوی اجرا شده را مشاهده کنید:


namespace Tests\Unit;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ProductTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$this->assertTrue(true);
}
}

با انجام این مرحله 7 تست مختلف و جامع را جایگزین تست ProductTest خواهید کرد.

2- تست Test Create Product With Middle ware

یک تست هیجان انگیز و ضروری برای بررسی صدور اجازه خرید در محصولی بدون توکن احراز هویت! این تست بررسی می کند که آیا یک کاربر می تواند بدون ورود محصولی را ایجاد کند، یا خیر؟ هدف از این تست این است که آزمون باید کد 401 Unauthenticated HTTP را برگرداند و محصول جدیدی ایجاد نکند. در این حالت می توانیم ایراد را پیدا کرده و سد امنیتی لازم را ایجاد کنیم. برای شروع کد زیر را در Product Test class وارد کنید:

[...]
public function testCreateProductWithMiddleware()
{
$data = [
'name' => "New Product",
'description' => "This is a product",
'units' => 20,
'price' => 10,
'image' => "https://images.pexels.com/photos/1000084/pexels-photo-1000084.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"
];
$response = $this->json('POST', '/api/products', $data);
$response->assertStatus(401);
$response->assertJson(['message' => "Unauthenticated."]);
}
[...]

3- تست Test Create Product

در این تست بررسی می کنیم که آیا کاربر می تواند یک محصول جعلی ایجاد کند، یا خیر؟ در این آزمایش از factory(\App\User::class)->create() موجود در Factory کمک کننده فریم ورک لاراول استفاده خواهد شد. ابتدا کاربر شی را ایجاد می کند و محتویات تعیین شده Fillable را پر می کند.
یک درخواست XHR به API در کاربر جعلی مانند this->actingAs($user, 'api')->json() ایجاد می کنیم و منتظر پاسخ کامل آن می مانیم. باید مشاهده کنیم که آیا شی پاسخ دهنده حاوی وضعیت موفقیت آمیز HTTP در کد 200 Ok است یا خیر؟ همچنین باید بررسی شود که پاسخ JSON حاوی آرگومان باشد و از داده های با استفاده از response→assertJson() کمک بگیرد:

public function testCreateProduct()
{
$data = [
'name' => "New Product",
'description' => "This is a product",
'units' => 20,
'price' => 10,
'image' => "https://images.pexels.com/photos/1000084/pexels-photo-1000084.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"
];
$user = factory(\App\User::class)->create();
$response = $this->actingAs($user, 'api')->json('POST', '/api/products', $data);
$response->assertStatus(200);
$response->assertJson(['status' => true]);
$response->assertJson(['message' => "Product Created!"]);
$response->assertJson(['data' => $data]);
}
[...]

4- تست Test Getting All Products

در این تست برای بازگرداندن همه محصولات API را فراخوانی خواهیم کرد تا وضعیت را در کد 200 Ok بررسی کنیم. همچنین باید توجه کنیم که ساختار خاصی با آرگومان های خاص را در پاسخ های بازگردانده شده داشته باشیم. چنانچه نتیجه داده ها ساختار خاصی داشته باشند، مطمئن هستیم که دقیق لازم را در اجرا تست بکار برده ایم و حتی می توان در مجموعه داده بزرگ نیز این تست را انجام داد:

[...]
public function testGettingAllProducts()
{
$response = $this->json('GET', '/api/products');
$response->assertStatus(200);
$response->assertJsonStructure(
[
[
'id',
'name',
'description',
'units',
'price',
'image',
'created_at',
'updated_at'
]
]
);
}
[...]

5- تست Test Update Product

این تست در Endpoint یا به اصطلاح در نقطه پایانی API ایجاد می شود که با اجرا آن همه محصولات موجود را با روش Call دریافت خواهیم کرد. بنابراین ابتدا محصولی را انتخاب می کنیم که توسط Endpoint بازگردانده شده است، این کار موجب می شود تا بتوانیم محصول واقعی را بروز رسانی کرده و خطاهای پرتاب API را در جهت رفع مورد بررسی قرار دهیم. در مرحله دوم سعی می کنیم تا یک محصول را انتخاب نموده و نام محصول را به روز می کنیم، سپس پیام ارسال شده برای محصول به روز شده را بررسی می کنیم:

[...]
public function testUpdateProduct()
{
$response = $this->json('GET', '/api/products');
$response->assertStatus(200);
$product = $response->getData()[0];
$user = factory(\App\User::class)->create();
$update = $this->actingAs($user, 'api')->json('PATCH', '/api/products/'.$product->id,['name' => "Changed for test"] );
$update->assertStatus(200);
$update->assertJson(['message' => "Product Updated!"]);
}
[...]

6- تست Test Upload Image

برای عملی شدن این آزمایش در Endpoint باید Upload File class را در Product Test class قرار دهیم:

[...]
use Illuminate\Http\UploadedFile;

use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
[...]

سپس از Uploaded File برای ایجاد فایل تصویری آپلود شده جعلی کمک می گیریم تا بدانیم آیا آپلود تصویر به درستی کار می کند یا خیر؟ توجه کنید که پاسخ برگشتی نباید تهی باشد:

[...]
public function testUploadImage()
{
$response = $this->json('POST', '/api/upload-file', [
'image' => UploadedFile::fake()->image('image.jpg')
]);
$response->assertStatus(201);
$this->assertNotNull($response->getData());
}
[...]

7- تست Test Delete Product

این تست دقیقاً همانند Test Update Product عمل می کند و تنها تفاوت در ارسال DELETEPOST Request می باشد:

[...]
public function testDeleteProduct()
{
$response = $this->json('GET', '/api/products');
$response->assertStatus(200);
$product = $response->getData()[0];
$user = factory(\App\User::class)->create();
$delete = $this->actingAs($user, 'api')->json('DELETE', '/api/products/'.$product->id);
$delete->assertStatus(200);
$delete->assertJson(['message' => "Product Deleted!"]);
}
[...]

8- تست Testing The Order Endpoints

برای راه اندازی تست دستور زیر را وارد کنید و ادمه دهید:

 php artisan make:test OrderTest --unit

اگر با باز کردن فایل tests/Unit/OrderTest.php الگوی ایجاد شده را میبینید، راه را درست آمده اید! اکنون می توانید با این الگوی ایجاد شده که در دسترس شما قرار گرفته است کار کنید:


namespace Tests\Unit;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class OrderTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$this->assertTrue(true);
}
}

توجه کنید که باید تمام توابع تست را در OrderTest class بنویسید.

9- تست Test Create Order

در این آزمایش برای ایجاد درخواست XHR Post به درخواست XHR در API، از کاربر جعلی استفاده می کنیم و منظر پاسخ موفقیت آمیز در کد 200 Ok می مانیم:

[...]
public function testCreateOrder()
{
$data = [
'product' => 1,
'quantity' => 20,
'address' => "No place like home"
];
$user = factory(\App\User::class)->create();
$response = $this->actingAs($user, 'api')->json('POST', '/api/orders', $data);
$response->assertStatus(200);
$response->assertJson(['status' => true]);
$response->assertJson(['message' => "Order Created!"]);
$response->assertJsonStructure(['data' => [
'id',
'product_id',
'user_id',
'quantity',
'address',
'created_at',
'updated_at'
]]);
}
[...]

10- تست Test Get All Orders

در این تست همانند برخی دیگر از تست های ذکر شده به Endpoint مراجعه می کنیم زیرا Endpoint مسئول گرفتن تمام سفارشات می باشد. پس از اجرا عملیات کد 200 Ok را بررسی کرده و آرگومان های خاص موجود در داده های برگشت داده شده را بازبینی می کنیم:

[...]
public function testCreateOrder()
{
$data = [
'product' => 1,
'quantity' => 20,
'address' => "No place like home"
];
$user = factory(\App\User::class)->create();
$response = $this->actingAs($user, 'api')->json('POST', '/api/orders', $data);
$response->assertStatus(200);
$response->assertJson(['status' => true]);
$response->assertJson(['message' => "Order Created!"]);
$response->assertJsonStructure(['data' => [
'id',
'product_id',
'user_id',
'quantity',
'address',
'created_at',
'updated_at'
]]);
}
[...]

11- تست Test Deliver Order

پس از انتخاب اولین Order در این تست سعی می کنیم Order را تحویل دهیم و داده ها را از پاسخ دریافت کنیم تا ببینیم آیا is_delivered attribute درست است یا خیر؟ توجه داشته باشید که id دقیقاً همان سعی به بروز رسانی ما در این تست است:

[...]
public function testDeliverOrder()
{
$user = factory(\App\User::class)->create();
$response = $this->actingAs($user, 'api')->json('GET', '/api/orders');
$response->assertStatus(200);
$order = $response->getData()[0];
$update = $this->actingAs($user, 'api')->json('PATCH', '/api/orders/'.$order->id."/deliver");
$update->assertStatus(200);
$update->assertJson(['message' => "Order Delivered!"]);
$updatedOrder = $update->getData('data');
$this->assertTrue($updatedOrder['data']['is_delivered']);
$this->assertEquals($updatedOrder['data']['id'], $order->id);
}
[...]

12- تست Test Update Order

در این مرحله نیز در قسمت Endpoint وضعیت کد 200 Ok را بررسی کرده و در پایان باید دقت کنیم که پس از بروز رسانی سفارش، پیام برگشته باشد:

[...]
public function testUpdateOrder()
{
$user = factory(\App\User::class)->create();
$response = $this->actingAs($user, 'api')->json('GET', '/api/orders');
$response->assertStatus(200);
$order = $response->getData()[0];
$update = $this->actingAs($user, 'api')->json('PATCH', '/api/orders/'.$order->id,['quantity' => ($order->id +5)]);
$update->assertStatus(200);
$update->assertJson(['message' => "Order Updated!"]);
}
[...]

بهترین نوع تست نویسی در لاراول

مرحله پایانی نحوه اجرای تست ها در Laravel

پس از آنکه به طور کامل نوشتن تست ها به پایان رسید، دستور زیر را در قسمت Terminal اجرا کنید:

 ./vendor/bin/phpunit
نحوه اجرای تست ها در Laravel پس از کدنویسی
نکته مهم! ممکن است در هنگام تست نویسی لاراول در سیستم ویندوز با خطا Test Upload Image مواجه شوید. در این صورت لازم است بدانید که مورد از مجوزهای ویندوز می باشد.

سخن آخر

تمام آنچه که باید در تست نویسی Laravel بررسی می کردید مانند راه اندازی اپلیکیشن، محیط تست و اجرای آن ها را در این مقاله علمی مطالعه نمودید. بنابراین با خیال راحت می توانید مشکلات و باگ های موجود در سیستم توسعه وب را پیدا کرده و برای حل آن ها زمان بگذارید. از طرفی می توانید مرحله به مرحله با مثال موجود در مقاله پیش رفته و از جواب دهی تست های خود مطمئن شوید. منتظر تجربیات شما در تست نویسی در لاراول هستیم.
چقدر این پست مفید بود؟ روی یک ستاره کلیک کنید تا به آن امتیاز دهید!
پست های پیشنهادی
php چیست
متوسط

php چیست و چه استفاده ای دارد: بررسی جامع

مفهوم کامل زبان php و مزیت های آن نسبت به سایر زبان ها!
تیم محتوا
1403/03/02
پیش نیازهای لازم برای طراحی سایت با لاراول
حرفه‌ای

پیش نیازهای لازم برای طراحی سایت با لاراول

بررسی آموزش پیش نیازهای لازم طراحی سایت با لاراول را به طور ...
تیم محتوا
1403/03/21
آموزش نصب npm در لاراول
حرفه‌ای

آموزش نصب npm در لاراول

دد
تیم محتوا
1403/03/23