Project

General

Profile

Task #96 » UnitTestGuide.md

Nghia Nguyen, 07/17/2025 04:16 AM

 

Hướng dẫn thay đổi Unit Test

📁 Cấu trúc thư mục Test

tests/
├── Feature/                    # Feature Tests - Test chức năng hoàn chỉnh
│   ├── ScenarioTest.php      
│   ├── Auth/                  # Test xác thực
│   ├── OwnerAccount/          # Test quản lý tài khoản
│   ├── Facility/              # Test quản lý Facility
│   ├── Order/                 # Test Order
│   └── ...
├── Unit/                      # Unit Tests - Test component riêng lẻ
│   └── ExampleTest.php
├── TestCase.php               # Base class cho tất cả test
└── CreatesApplication.php     # Trait tạo application

🗄️ Database Test

2 Database riêng biệt:

// config/database.php
'testing' => [           // Database chính cho test
   database' => env('DB_DATABASE,testing')
],
rakuichi_testing' => [  // Database phụ cho test (Rakuichi)
   database' => env('RO_DB_DATABASE',rakuichi_testing)
]

Cấu hình trong phpunit.xml:

<env name="DB_DATABASE" value="testing"/>
<env name="RO_DB_DATABASE" value="rakuichi_testing"/>

📊 Data Mẫu (Seeders)

Vị trí tạo data:

database/seeders/
├── TestCreateRakuichiTablesSeeder.php  # Tạo bảng cho Rakuichi
├── TestOwnerAccountSeeder.php          # Data tài khoản owner
├── TestAdminAccountSeeder.php          # Data tài khoản admin
├── TestFacilityCategorySeeder.php      # Data danh mục Facility
├── TestTaxSeeder.php                   # Data thuế
├── TestHolidayMasterSeeder.php         # Data ngày lễ
├── TestOrderSeeder.php                 # Data order
└── TestInitialDataSeeder.php           # Data khởi tạo

Reset database trong test:

public function resetDatabase(): void
{
    Artisan::call('migrate:refresh');
    $this->seed(TestCreateRakuichiTablesSeeder::class);
    $this->seed(TestOwnerAccountSeeder::class);
    $this->seed(TestAdminAccountSeeder::class);
    $this->seed(TestFacilityCategorySeeder::class);
    $this->seed(TestTaxSeeder::class);
    $this->seed(TestHolidayMasterSeeder::class);
}

🚀 Cách chạy Test

Chạy tất cả test:

php artisan test

Chạy test cụ thể:

# Chạy 1 file test
php artisan test tests/Feature/ScenarioTest.php

# Chạy1d test
php artisan test --filter test_オーナーメインアカウントを登録できること

# Chạy test theo suite
php artisan test --testsuite=Feature
php artisan test --testsuite=Unit

# Chạy test với verbose
php artisan test -v

Chạy với coverage:

php artisan test --coverage

Chạy test song song:

php artisan test --parallel

✏️ Thêm Test Mới

1 Tạo file test mới:

# Tạo Feature test
php artisan make:test MyFeatureTest

# Tạo Unit test  
php artisan make:test MyUnitTest --unit

# Tạo test với model
php artisan make:test UserTest --model=User

2. Cấu trúc file test:

<?php

namespace Tests\Feature;

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

class MyFeatureTest extends TestCase
{
    use RefreshDatabase; // Tự động refresh database

    protected function setUp(): void
    [object Object]       parent::setUp();
        $this->resetDatabase(); // Reset data mẫu
    }

    public function test_my_function()
    {
        // Arrange - Chuẩn bị data
        $data = [
         name => User',
           email =>test@example.com'
        ];

        // Act - Thực hiện action
        $response = $this->post('/api/my-endpoint', $data);

        // Assert - Kiểm tra kết quả
        $response->assertOk();
        $this->assertDatabaseHas('users, [
         name => User',
           email =>test@example.com'
        ]);
    }
}

3. Các assertion phổ biến:

// HTTP Response
$response->assertOk();                    // Status 200
$response->assertCreated();               // Status 201
$response->assertNotFound();              // Status 404
$response->assertUnauthorized();          // Status 401
$response->assertForbidden();             // Status 403
$response->assertValidationErrors(['field]); // Validation errors

// Database
$this->assertDatabaseHas(table', [column' => value]);
$this->assertDatabaseMissing(table', [column' => value]);
$this->assertDatabaseCount('table', 5);

// Authentication
$this->assertAuthenticated();
$this->assertGuest();

🔧 Cấu hình môi trường

1. Tạo file .env.testing:

APP_ENV=testing
DB_CONNECTION=testing
DB_DATABASE=testing
RO_DB_DATABASE=rakuichi_testing
CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_CONNECTION=sync
MAIL_MAILER=array

2. Setup database test:

# Tạo database test
mysql -u root -p -e "CREATE DATABASE testing;mysql -u root -p -e "CREATE DATABASE rakuichi_testing;"

# Chạy migration cho test
php artisan migrate --env=testing

# Chạy seeder cho test
php artisan db:seed --env=testing

3. Cấu hình trong phpunit.xml:

<php>
    <env name="APP_ENV" value="testing"/>
    <env name="DB_CONNECTION" value="testing"/>
    <env name="DB_DATABASE" value="testing"/>
    <env name="RO_DB_DATABASE" value="rakuichi_testing"/>
    <env name="CACHE_DRIVER value=array"/>
    <env name="SESSION_DRIVER value=array"/>
    <env name=QUEUE_CONNECTION" value="sync"/>
    <env name="MAIL_MAILERvalue="array/>
</php>

📝 Best Practices

1. Naming Convention:

// Tên method test nên mô tả rõ ràng
public function test_user_can_login_with_valid_credentials()
public function test_user_cannot_login_with_invalid_credentials()
public function test_admin_can_create_new_user()

2. Test Structure (AAA Pattern):

public function test_example()
[object Object]  // Arrange - Chuẩn bị
    $user = User::factory()->create();
    
    // Act - Thực hiện
    $response = $this->actingAs($user)->get('/dashboard');
    
    // Assert - Kiểm tra
    $response->assertOk();
}

3. Sử dụng Factories:

// Tạo data test với factory
$user = User::factory()->create();
$users = User::factory()->count(5)->create();

// Tạo data với relationship
$user = User::factory()
    ->has(Order::factory()->count(3))
    ->create();

4. Mocking:

// Mock external service
$this->mock(EmailService::class, function ($mock) {
    $mock->shouldReceive('send')->once()->andReturn(true);
});

🐛 Debug Test

1. Dump response:

$response = $this->get('/api/users);dd($response->json()); // Dump JSON response

2Log trong test:

Log::info('Test data:', $data);

3. Chạy test với debug:

php artisan test --verbose --stop-on-failure

📊 Test Coverage

Xem coverage report:

# Chạy test với coverage
php artisan test --coverage

# Chạy với HTML report
php artisan test --coverage-html coverage/

Cấu hình coverage trong phpunit.xml:

<coverage processUncoveredFiles="true">
    <include>
        <directory suffix=".php>./app</directory>
    </include>
    <exclude>
        <directory suffix=".php">./app/Console</directory>
    </exclude>
</coverage>

🔄 CI/CD Integration

GitHub Actions example:

name: Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.1   - name: Install dependencies
        run: composer install
      - name: Run tests
        run: php artisan test

📚 Tài liệu tham khảo

    (1-1/1)