خطوط أنابيب الاختبار في التكامل والنشر المستمر
تعمل خطوط أنابيب التكامل المستمر والنشر المستمر (CI/CD) على أتمتة عملية الاختبار الخاصة بك، مما يضمن اختبار كل تغيير في الكود بشكل شامل قبل الوصول إلى الإنتاج. يغطي هذا الدرس إعداد خطوط أنابيب الاختبار الآلي باستخدام منصات CI/CD الشهيرة.
فهم اختبار CI/CD
يقوم اختبار CI/CD تلقائيًا بتشغيل مجموعة الاختبارات الخاصة بك كلما تم دفع تغييرات الكود إلى المستودع الخاص بك. هذا يوفر ردود فعل فورية ويمنع الأخطاء من الوصول إلى الإنتاج.
الفوائد الرئيسية:
- ردود فعل فورية على تغييرات الكود
- تنفيذ تلقائي للاختبارات على كل commit
- تنفيذ اختبارات متوازية لنتائج أسرع
- تاريخ الاختبار وتحليل الاتجاهات
- التكامل مع خطوط أنابيب النشر
GitHub Actions لاختبار Laravel
GitHub Actions هي منصة CI/CD قوية متكاملة مباشرة في مستودعات GitHub. إليك سير عمل اختبار Laravel شامل:
# .github/workflows/tests.yml
name: Laravel Tests
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
laravel-tests:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: [8.1, 8.2, 8.3]
laravel-version: [10.*, 11.*]
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: testing
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
redis:
image: redis:7
ports:
- 6379:6379
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: mbstring, dom, fileinfo, mysql, redis
coverage: xdebug
- name: Cache Composer dependencies
uses: actions/cache@v3
with:
path: vendor
key: composer-${{ matrix.php-version }}-${{ matrix.laravel-version }}-${{ hashFiles('**/composer.lock') }}
restore-keys: |
composer-${{ matrix.php-version }}-${{ matrix.laravel-version }}-
- name: Install Dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel-version }}" --no-interaction --no-update
composer install --prefer-dist --no-interaction --no-progress
- name: Copy Environment File
run: cp .env.example .env
- name: Generate Application Key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Run Database Migrations
env:
DB_CONNECTION: mysql
DB_HOST: 127.0.0.1
DB_PORT: 3306
DB_DATABASE: testing
DB_USERNAME: root
DB_PASSWORD: password
run: php artisan migrate --force
- name: Execute Unit Tests
env:
DB_CONNECTION: mysql
DB_HOST: 127.0.0.1
DB_PORT: 3306
DB_DATABASE: testing
DB_USERNAME: root
DB_PASSWORD: password
REDIS_HOST: 127.0.0.1
REDIS_PORT: 6379
run: php artisan test --parallel --coverage --min=80
- name: Upload Coverage Reports
uses: codecov/codecov-action@v3
with:
files: ./coverage.xml
flags: unittests
name: codecov-umbrella
إعداد GitLab CI
يوفر GitLab CI/CD ميزات قوية لاختبار تطبيقات Laravel مع سجل الحاويات المدمج وخيارات النشر:
# .gitlab-ci.yml
image: php:8.2-fpm
variables:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: testing
MYSQL_USER: laravel
MYSQL_PASSWORD: laravel
DB_HOST: mysql
stages:
- build
- test
- deploy
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- vendor/
- node_modules/
before_script:
- apt-get update -yqq
- apt-get install -yqq git libzip-dev libpq-dev libcurl4-gnutls-dev
- docker-php-ext-install pdo_mysql zip
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install --prefer-dist --no-ansi --no-interaction --no-progress --no-scripts
- cp .env.example .env
- php artisan key:generate
- php artisan config:clear
build:
stage: build
script:
- composer validate
- composer install --prefer-dist --no-ansi --no-interaction --no-progress --no-scripts
- npm install
- npm run build
artifacts:
paths:
- vendor/
- node_modules/
- public/build/
expire_in: 1 hour
unit-tests:
stage: test
services:
- mysql:8.0
dependencies:
- build
script:
- php artisan migrate --seed
- php artisan test --testsuite=Unit --coverage-cobertura=coverage.xml
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
feature-tests:
stage: test
services:
- mysql:8.0
- redis:latest
dependencies:
- build
script:
- php artisan migrate --seed
- php artisan test --testsuite=Feature
retry:
max: 2
when: runner_system_failure
browser-tests:
stage: test
services:
- mysql:8.0
- selenium/standalone-chrome:latest
dependencies:
- build
script:
- php artisan dusk:chrome-driver --detect
- php artisan migrate --seed
- php artisan serve > /dev/null 2>&1 &
- sleep 5
- php artisan dusk
artifacts:
when: on_failure
paths:
- tests/Browser/screenshots/
- tests/Browser/console/
expire_in: 7 days
التنفيذ المتوازي للاختبارات
تشغيل الاختبارات بشكل متوازٍ يقلل بشكل كبير من وقت تنفيذ خط الأنابيب:
# GitHub Actions مع الاختبار المتوازي
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test-suite: [Unit, Feature, Browser]
steps:
- uses: actions/checkout@v4
- name: Run ${{ matrix.test-suite }} Tests
run: php artisan test --testsuite=${{ matrix.test-suite }} --parallel
# إعداد PHPUnit للتنفيذ المتوازي
<!-- phpunit.xml -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
processIsolation="false"
stopOnFailure="false">
<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>
<env name="PARALLEL_TESTING" value="true"/>
<env name="PARATEST_PROCESSES" value="4"/>
</php>
</phpunit>
تقارير الاختبار والقطع الأثرية
تساعد تقارير الاختبار الشاملة في تتبع نتائج الاختبار بمرور الوقت:
// إنشاء تقرير اختبار HTML
php artisan test --coverage-html=coverage-report
// إنشاء شارة التغطية
php artisan test --coverage-clover=coverage.xml
// تقرير JUnit XML لأنظمة CI
php artisan test --log-junit=junit.xml
أفضل ممارسات تقارير الاختبار:
- تخزين تقارير الاختبار كقطع أثرية لمدة 30-90 يومًا
- إنشاء شارات التغطية لملفات README
- تتبع اتجاهات وقت تنفيذ الاختبار
- إعداد الإخطارات لفشل الاختبارات
- أرشفة لقطات الشاشة والسجلات للاختبارات الفاشلة
الاختبار الخاص بالبيئة
تكوين بيئات اختبار مختلفة لسيناريوهات متنوعة:
# .github/workflows/tests.yml
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
environment: [staging, production]
steps:
- name: Run tests against ${{ matrix.environment }}
env:
APP_ENV: ${{ matrix.environment }}
APP_URL: ${{ secrets[format('{0}_APP_URL', matrix.environment)] }}
DB_DATABASE: ${{ secrets[format('{0}_DB_DATABASE', matrix.environment)] }}
run: php artisan test
تعبئة قاعدة البيانات في CI
تعبئة قواعد بيانات الاختبار بكفاءة في خط الأنابيب الخاص بك:
// استخدام seeder مخصص لـ CI
class CISeed extends Seeder
{
public function run()
{
// إنشاء بيانات الاختبار الأساسية فقط
User::factory()->count(10)->create();
Product::factory()->count(50)->create();
// تخطي العمليات التي تستغرق وقتًا طويلاً
if (!app()->environment('ci')) {
$this->call(HeavyDataSeeder::class);
}
}
}
# في سير عمل CI
- name: Seed Database
run: php artisan db:seed --class=CISeed
استراتيجيات التخزين المؤقت
تحسين سرعة خط الأنابيب باستخدام التخزين المؤقت الذكي:
# التخزين المؤقت في GitHub Actions
- name: Cache Composer packages
uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Cache NPM packages
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- name: Cache Laravel Routes
uses: actions/cache@v3
with:
path: bootstrap/cache
key: ${{ runner.os }}-routes-${{ hashFiles('routes/*.php') }}
الإخطارات والتكاملات
إعداد الإخطارات لنتائج الاختبار:
# إخطار Slack عند الفشل
- name: Notify Slack on Failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Tests failed on ${{ github.ref }}'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
- name: Create GitHub Issue on Failure
if: failure()
uses: actions/github-script@v6
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: 'CI Tests Failed: ${{ github.sha }}',
body: 'Tests failed in workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
})
فحص الأمان في خطوط الأنابيب
دمج فحوصات الأمان في خط أنابيب الاختبار الخاص بك:
# فحص ثغرات الأمان
- name: Security Audit
run: |
composer audit
npm audit
- name: Static Analysis
run: |
vendor/bin/phpstan analyse --memory-limit=2G
vendor/bin/psalm --show-info=true
- name: Code Quality Check
run: vendor/bin/php-cs-fixer fix --dry-run --diff
الأخطاء الشائعة في خطوط الأنابيب:
- عدم تخزين التبعيات مؤقتًا (بناء بطيء)
- تشغيل جميع الاختبارات بشكل متسلسل (وقت ضائع)
- تجاهل الاختبارات غير المستقرة (نتائج غير موثوقة)
- متغيرات البيئة المفقودة (فشل الاختبارات)
- عدم تنظيف الموارد (تسرب الذاكرة)
بوابات النشر
استخدام نتائج الاختبار للتحكم في عمليات النشر:
# النشر فقط إذا نجحت الاختبارات
deploy:
stage: deploy
needs:
- unit-tests
- feature-tests
- browser-tests
only:
- main
script:
- echo "Deploying to production..."
- ./deploy.sh
تمرين:
- أنشئ سير عمل GitHub Actions يشغل اختبارات Laravel الخاصة بك عند الدفع
- أضف تنفيذ الاختبار المتوازي لاختبارات Unit و Feature
- قم بتكوين خدمات MySQL و Redis
- قم بإعداد تقارير تغطية الكود
- أضف استراتيجية تخزين مؤقت لتبعيات Composer
- إضافي: أضف إخطارات Slack لفشل الاختبارات
مراقبة أداء خط الأنابيب
تتبع وتحسين وقت تنفيذ خط الأنابيب الخاص بك:
// إنشاء تقرير أداء خط الأنابيب
php artisan test --profile --testdox
// الإخراج:
// Time: 00:02.548, Memory: 24.00 MB
//
// Slowest tests:
// - ProductTest::it_can_process_large_orders (1.2s)
// - UserTest::it_can_upload_profile_image (0.8s)
// - OrderTest::it_can_generate_invoice_pdf (0.6s)
قائمة التحقق من تحسين خط الأنابيب:
- تخزين التبعيات مؤقتًا بشكل مكثف
- استخدام التنفيذ المتوازي لمجموعات الاختبار
- تشغيل الاختبارات السريعة أولاً (استراتيجية الفشل السريع)
- استخدام معاملات قاعدة البيانات بدلاً من الترحيلات
- محاكاة استدعاءات API الخارجية
- استخدام قواعد البيانات في الذاكرة عندما يكون ذلك ممكنًا
- تنظيف بيانات الاختبار بكفاءة
ملخص أفضل الممارسات
- تشغيل الاختبارات على كل commit وطلب سحب
- استخدام matrix builds لاختبار إصدارات PHP/Laravel متعددة
- تنفيذ الاختبار المتوازي لتقليل وقت التنفيذ
- تخزين التبعيات والقطع الأثرية مؤقتًا
- إنشاء وأرشفة تقارير الاختبار
- إعداد إخطارات ذات مغزى
- استخدام بوابات النشر لمنع الإصدارات المعطلة
- مراقبة وتحسين أداء خط الأنابيب
- تضمين فحوصات الأمان في خط الأنابيب الخاص بك
- توثيق إعداد CI/CD الخاص بك
يوفر خط أنابيب CI/CD المكون جيدًا الثقة بأن الكود الخاص بك يعمل بشكل صحيح قبل وصوله إلى الإنتاج، مما يتيح عمليات نشر أسرع وأكثر أمانًا.