Files
agent-unit-testing/docs/00-environment-and-setup.md
T
Pham-Tan-Thien 2045c856e9 feat: complete Smartgift AI Laravel unit testing toolkit
- Add 10 core testing guides (setup, AAA principles, PHPUnit/Pest, mocking, anti-patterns, PHP 8.4+, debugging, data factories, advanced edge cases)
- Add 13 component testing guides covering all Laravel layers
- Add standard templates for PHPUnit 10/11 and Pest v2/v3 including ArchitectureTest
- Add Docker smart test runner, dependency installer, and CI/CD templates (GitHub Actions, GitLab CI)
- Add 4 Claude Code skills (laravel-test-setup, laravel-unit-test with --all mode, laravel-test-review, laravel-mock-helper)
- Add single unified installer script (sg-install-unit-testing.sh) with global support, CLI runners, and 1-click updater (sg-test-update)
- Add comprehensive documentation (README.md, USAGE-GUIDE.md)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-07 16:41:37 +07:00

7.2 KiB

00. Environment & Setup Guide for Laravel Unit Testing

Hướng dẫn thiết lập và chuẩn hóa môi trường kiểm thử (Testing Environment) cho mọi dự án Laravel (Laravel 9, 10, 11).


1. Yêu cầu Thư viện & Dependencies (Composer)

Trước khi viết bất kỳ file Unit Test nào, dự án cần có đầy đủ các thư viện kiểm thử cần thiết trong require-dev.

A. Kiểm tra phiên bản Laravel & Test Framework

Xác định phiên bản Laravel trong composer.json:

  • Laravel 9 (PHP 8.0 - 8.1): Thường đi kèm phpunit/phpunit: ^9.5.
  • Laravel 10 (PHP 8.1 - 8.2): Hỗ trợ phpunit/phpunit: ^10.0 hoặc pestphp/pest: ^2.0.
  • Laravel 11 (PHP 8.2 - 8.3+): Mặc định pestphp/pest: ^2.0|^3.0 hoặc phpunit/phpunit: ^10.5|^11.0.

B. Cài đặt các gói cốt lõi (Core Dev Packages)

Nếu dự án dùng PHPUnit:

composer require --dev phpunit/phpunit mockery/mockery fakerphp/faker --with-all-dependencies

Nếu dự án dùng Pest PHP:

composer require --dev pestphp/pest pestphp/pest-plugin-laravel mockery/mockery fakerphp/faker --with-all-dependencies
  • Chạy song song (Parallel Testing):
    composer require --dev brianium/paratest
    # Laravel 9+ có sẵn lệnh: php artisan test --parallel
    
  • Làm đẹp output CLI:
    composer require --dev nunomaduro/collision
    

2. Cấu hình Môi trường Test (phpunit.xml & .env.testing)

Một trong những sai lầm nghiêm trọng nhất là để test chạy vào Database dev/staging. Cần cấu hình cách ly tuyệt đối.

A. Tối ưu hóa phpunit.xml (hoặc phpunit.xml.dist)

Đảm bảo thẻ <php> chứa các cấu hình sau:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         colors="true">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <php>
        <!-- Môi trường test -->
        <env name="APP_ENV" value="testing"/>
        <env name="APP_MAINTENANCE_DRIVER" value="file"/>
        
        <!-- Tăng tốc mã hóa mật khẩu trong lúc test (từ 10-12 vòng xuống 4 vòng) -->
        <env name="BCRYPT_ROUNDS" value="4"/>
        
        <!-- Tắt cache, session, queue, mail thật -->
        <env name="CACHE_STORE" value="array"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_CONNECTION" value="sync"/>
        <env name="MAIL_MAILER" value="array"/>
        <env name="PULSE_ENABLED" value="false"/>
        <env name="TELESCOPE_ENABLED" value="false"/>
        
        <!-- Database cách ly: SQLite In-memory -->
        <env name="DB_CONNECTION" value="sqlite"/>
        <env name="DB_DATABASE" value=":memory:"/>
    </php>
</phpunit>

B. File .env.testing

Nếu dự án ưu tiên dùng .env.testing hơn phpunit.xml, tạo file .env.testing tại thư mục root:

APP_ENV=testing
APP_KEY=base64:FakeKeyForTestingPurposesOnly1234567890=
APP_DEBUG=true

BCRYPT_ROUNDS=4
CACHE_STORE=array
CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_CONNECTION=sync
MAIL_MAILER=array

DB_CONNECTION=sqlite
DB_DATABASE=:memory:

3. Chiến lược Xử lý Database trong Kiểm thử

Chiến lược 1: SQLite In-memory (Mặc định - Khuyến nghị cho 90% Unit Test)

  • Ưu điểm: Tốc độ cực nhanh (vài milliseconds), không tạo rác trên ổ cứng, tự hủy sau mỗi test process.
  • Yêu cầu: PHP phải kích hoạt extension pdo_sqlite và sqlite3.

Chiến lược 2: Xử lý các hàm MySQL đặc thù (MySQL-specific functions)

Nếu code nguồn dùng các hàm raw của MySQL như JSON_EXTRACT, JSON_CONTAINS, DATE_FORMAT, SQLite sẽ văng lỗi no such function. Cách xử lý:

  1. Đăng ký SQLite custom function trong TestCase::setUp():
    protected function setUp(): void
    {
        parent::setUp();
    
        if (DB::connection() instanceof \Illuminate\Database\SQLiteConnection) {
            $pdo = DB::connection()->getPdo();
            // Giả lập hàm DATE_FORMAT của MySQL trong SQLite
            $pdo->sqliteCreateFunction('DATE_FORMAT', function ($date, $format) {
                return date('Y-m-d', strtotime($date));
            }, 2);
    
            // Giả lập JSON_CONTAINS
            $pdo->sqliteCreateFunction('JSON_CONTAINS', function ($json, $val) {
                $array = json_decode($json, true) ?? [];
                return in_array(trim($val, '"'), $array) ? 1 : 0;
            }, 2);
        }
    }
    
  2. Nếu dự án có quá nhiều Stored Procedures hoặc SQL phức tạp: Sử dụng một container MySQL test riêng (xem mục Docker bên dưới) thay vì SQLite.

4. Chạy Test qua Docker (Docker Integration)

Kịch bản 1: Dự án dùng Laravel Sail

Laravel Sail đã cấu hình sẵn container test:

# Chạy toàn bộ test
./vendor/bin/sail test

# Chạy riêng Unit Test
./vendor/bin/sail test --testsuite=Unit

# Chạy kèm tính Code Coverage
./vendor/bin/sail test --coverage

Kịch bản 2: Dự án dùng Custom Docker Compose

Xác định tên service PHP trong docker-compose.yml (thường là app, php, backend, workspace):

# Cú pháp chạy
docker compose exec -T <service_name> php artisan test

# Ví dụ với service 'app':
docker compose exec -T app php artisan test --testsuite=Unit --filter=UserServiceTest

Kịch bản 3: Docker Test Runner độc lập (templates/docker/docker-compose.test.yml)

Nếu dự án chưa có Docker hoặc môi trường Docker chính quá nặng nề, có thể khởi tạo một container test tối giản chỉ chứa PHP-CLI + SQLite + PCOV.


5. Cấu hình Code Coverage (PCOV vs Xdebug)

Để đo độ phủ test (Coverage):

  • Khuyến nghị dùng PCOV: Nhanh gấp 5-10 lần Xdebug, chỉ phục vụ đo coverage không làm chậm quá trình chạy test.
    • Cài đặt trên Ubuntu/Debian container: pecl install pcov && docker-php-ext-enable pcov
    • Lệnh chạy: php artisan test --coverage --min=80
  • Nếu dùng Xdebug: Cần đặt biến môi trường XDEBUG_MODE=coverage.

6. Checklist Kiểm tra Sẵn sàng (Ready-to-Test Checklist)

Trước khi bắt đầu sinh unit test, hãy xác nhận các mục sau:

  1. Đã chạy composer install không lỗi.
  2. Extension pdo_sqlite đã được bật (kiểm tra bằng php -m | grep sqlite).
  3. APP_KEY đã tồn tại trong file môi trường test.
  4. Chạy lệnh php artisan test (hoặc tương đương qua Docker) ra kết quả xanh (Pass) với các test mặc định của Laravel.
  5. Đã cấu hình DB_DATABASE=:memory: để bảo vệ dữ liệu dev/local.