آموزش تست نویسی در لاراول با مثال
0 نظر
یکشنبه 20 خرداد
مطالعه: 30 دقیقه
php
چرا در زبان لاراول به تست نویسی نیاز داریم؟
لاراول می گوید تست نویسی کار آسانی است، زیرا این تست ها با انجام دادن بخشی از کدها تمام خطاهای موجود را نمایش می دهند. پس اگر در حال راه اندازی یک ویژگی جدید در برنامه خود هستید می توانید از این روش به عنوان دستیار بررسی کدهای جدید و قدیمی استفاده کنید. آزمایش مجدد همه ویژگی های برنامه، همه هدف ما در این تست نویسی خواهد بود که در ادامه بیشتر با این مبحث آشنا خواهید شد.پیش نیازهای تست نویسی در 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=LaravelAPP_ENV=testingAPP_KEY=base64:5CpEFQ9UTR543dbJUsT3araoSSyxuN8NF92gCJJXpk8=APP_DEBUG=trueAPP_URL=http://localhostLOG_CHANNEL=stackDB_CONNECTION=sqliteDB_DATABASE=/absolute/path/to/test.sqliteBROADCAST_DRIVER=logCACHE_DRIVER=arraySESSION_DRIVER=arraySESSION_LIFETIME=120QUEUE_DRIVER=syncMAIL_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 می مانیم:
10- تست Test Get All Orders
در این تست همانند برخی دیگر از تست های ذکر شده به Endpoint مراجعه می کنیم زیرا Endpoint مسئول گرفتن تمام سفارشات می باشد. پس از اجرا عملیات کد 200 Ok را بررسی کرده و آرگومان های خاص موجود در داده های برگشت داده شده را بازبینی می کنیم:
11- تست Test Deliver Order
پس از انتخاب اولین Order در این تست سعی می کنیم Order را تحویل دهیم و داده ها را از پاسخ دریافت کنیم تا ببینیم آیا is_delivered attribute درست است یا خیر؟ توجه داشته باشید که id دقیقاً همان سعی به بروز رسانی ما در این تست است:
12- تست Test Update Order
در این مرحله نیز در قسمت Endpoint وضعیت کد 200 Ok را بررسی کرده و در پایان باید دقت کنیم که پس از بروز رسانی سفارش، پیام برگشته باشد:

نکته مهم! ممکن است در هنگام تست نویسی لاراول در سیستم ویندوز با خطا Test Upload Image مواجه شوید. در این صورت لازم است بدانید که مورد از مجوزهای ویندوز می باشد.
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

نکته مهم! ممکن است در هنگام تست نویسی لاراول در سیستم ویندوز با خطا Test Upload Image مواجه شوید. در این صورت لازم است بدانید که مورد از مجوزهای ویندوز می باشد.