حيل لاختبار تطبيقات الويب Laravel باستخدام المصانع النموذجية

المقدمة


دعونا نتخيل أننا نقوم بتطوير تطبيق ويب صغير على إصدار Laravel أعلى من 6 ونريد كتابة اختبارات له.


محتوى المقالة موضح أدناه:


  1. وصف المجال
  2. إنشاء التطبيق
  3. إنشاء الكيان
  4. اختبارات الكتابة
  5. مشكلة
  6. القرار

وصف المجال


سنقوم بتطوير متجر على الإنترنت حيث يمكن لبعض المستخدمين تقديم طلب معين. مما ورد أعلاه ، نحصل على أن الكيانات الرئيسية لمجال الموضوع ستكون المستخدم والنظام والسلع. هناك علاقة رأس بأطراف بين المستخدم والطلب ، أي أنه يمكن للمستخدم الحصول على العديد من الطلبات ، ولدى الطلب مستخدم واحد فقط (مطلوب مستخدم للطلب). هناك علاقة بين الكثير والكثير بين الطلب والبضائع ، لأن البضائع يمكن أن تكون في أوامر مختلفة ويمكن أن يتكون الطلب من العديد من السلع. من أجل البساطة ، نحذف المنتجات ونركز فقط على المستخدمين والطلبات.


إنشاء التطبيق


من السهل جدًا إنشاء تطبيقات Laravel باستخدام حزمة صانع التطبيقات . بعد تثبيته ، يتناسب إنشاء تطبيق جديد مع أمر واحد:


laravel new shop

إنشاء الكيان


, — . Laravel , . , . :


php artisan make:model Order -m -f

App/, database/migrations/ database/factories/.


. , . - :


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateOrdersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('orders');
    }
}

. fillable :


<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Order extends Model
{
    protected $fillable = ['user_id'];

    /**
     * Relation to user
     * @return BelongsTo
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}

. , , id.


<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Order;
use App\User;
use Faker\Generator as Faker;

$factory->define(Order::class, function (Faker $faker) {
    return [
        'user_id' => factory(User::class)->create()->id
    ];
});

, .



, Laravel PHPUnit . :


php artisan make:test OrderTest

tests/Feature/. RefreshDatabase.


№1.


<?php

namespace Tests\Feature;

use App\Order;
use App\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class OrderTest extends TestCase
{
    use RefreshDatabase;

    /** @test */
    public function order_factory_can_create_order()
    {
        // When we use Order factory
        $order = factory(Order::class)->create();
        // Then we should have new Order::class instance
        $this->assertInstanceOf(Order::class, $order);
    }
}

!


№2.


/** @test */
public function order_should_have_user_relation()
{
    // When we use Order factory
    $order = factory(Order::class)->create();
    // Then we should have new Order::class instance with user relation
    $this->assertNotEmpty($order->user_id);
    $this->assertInstanceOf(User::class, $order->user);
}

!


№3. ,


/** @test */
public function we_can_provide_user_id_to_order_factory()
{
    // Given user
    $user = factory(User::class)->create();
    // When we use Order factory and provide user_id parameter
    $order = factory(Order::class)->create(['user_id' => $user->id]);
    // Then we should have new Order::class instance with provided user_id
    $this->assertEquals($user->id, $order->user_id);
}

!


, , . , , .


№4. ,


/** @test */
public function when_we_create_one_order_one_user_should_be_created()
{
    // Given user
    $user = factory(User::class)->create();
    // When we use Order factory and provide user_id parameter
    $order = factory(Order::class)->create(['user_id' => $user->id]);
    // Then we should have new Order::class instance with provided user_id
    $this->assertEquals($user->id, $order->user_id);
    // Let's check that system has one user in DB
    $this->assertEquals(1, User::count());
}

! , . ? .



, , — . , , . . , , . , .



, . PHP , n- — func_get_arg(), . , () Faker, — , create() . , , () . , , . :


$factory->define(Order::class, function (Faker $faker) {
    //    
    $passedArguments = func_get_arg(1);
    return [
        'user_id' => function () use ($passedArguments) {
            //    user_id,   
            if (! array_key_exists('user_id', $passedArguments)) {
                return factory(User::class)->create()->id;
            }
        }
    ];
});

№4 — !


هذا كل ما أردت مشاركته. غالبًا ما أواجه مشكلة أنه من الضروري التحكم في عدد الكيانات بعد إجراء ما داخل النظام ، ولا يتعامل التنفيذ القياسي للمصنع مع هذا.


سأكون سعيدًا لسماع حيلك التي تستخدمها عند التطوير في Laravel أو PHP.


All Articles