Brain Monkey برای وردپرس چرا ضروری است؟ این پرسشی است که در مرز میان «تست‌نویسی به‌عنوان کار اضافه» و «تست‌نویسی به‌عنوان بخشی از معماری» قرار می‌گیرد. Brain Monkey یک کتابخانه سبک برای mocking توابع و کلاس‌های وردپرس در تست‌های PHPUnit است که بدون نیاز به نصب کامل وردپرس، امکان تست واحد افزونه‌ها و قالب‌ها را فراهم می‌کند. برخلاف WordPress Test Suite که وردپرس را به‌طور کامل بارگذاری می‌کند و به پایگاه داده نیاز دارد، Brain Monkey با استفاده از Monkey Patching توابع سراسری مانند get_option، apply_filters و wp_remote_get را شبیه‌سازی می‌کند. همین ویژگی، تست‌ها را از چند ثانیه به چند میلی‌ثانیه کاهش می‌دهد و امکان اجرای آن‌ها را در هر محیطی — بدون MySQL، بدون وردپرس — فراهم می‌کند. Brain Monkey سه مشکل اصلی تست وردپرس را حل می‌کند: سرعت پایین تست‌ها، وابستگی به پایگاه داده، و پیچیدگی راه‌اندازی محیط تست. در پروژه‌های واقعی، این کتابخانه تفاوت بین «تست‌هایی که هرگز اجرا نمی‌شوند» و «تست‌هایی که در هر commit اجرا می‌شوند» را می‌سازد. اگر روی افزونه یا کتابخانه‌ای کار می‌کنید که منطق آن قابل جداسازی از وردپرس است، Brain Monkey یکی از مؤثرترین ابزارهایی است که می‌توانید انتخاب کنید.

نخستین‌باری که تست‌های یک افزونه وردپرسی را نوشتیم، متوجه شدیم هر تست چند ثانیه طول می‌کشد و کل مجموعه در چند دقیقه اجرا می‌شود. این کندی، انگیزه اجرای تست‌ها را از بین می‌برد. بعد از مهاجرت به Brain Monkey، همان مجموعه در چند ثانیه اجرا شد. این تفاوت، نقطه شروعی بود برای بازنگری کامل معماری تست در پروژه‌ها. در این نوشتار، از مفاهیم پایه تا سناریوهای پیشرفته Brain Monkey را بررسی می‌کنیم.

Brain Monkey چیست و چه مسئله‌ای را حل می‌کند؟

Brain Monkey یک کتابخانه PHP است که برای تست واحد کدهایی طراحی شده که به توابع و کلاس‌های وردپرس وابسته‌اند. این کتابخانه توسط Brain Monkey توسعه یافته و در مخزن Composer با نام brain/monkey منتشر می‌شود. Brain Monkey از دو ابزار زیربنایی استفاده می‌کند: Patchwork برای Monkey Patching توابع سراسری، و Mockery برای ساخت اشیای شبیه‌سازی‌شده.

مسئله اصلی که Brain Monkey حل می‌کند، وابستگی مستقیم کد وردپرسی به توابع سراسری است. برای مثال، تابع get_option() یک تابع سراسری است که در همه جای وردپرس استفاده می‌شود. اگر بخواهید تابعی را که از این تابع استفاده می‌کند تست کنید، باید یا وردپرس را بارگذاری کنید یا این تابع را شبیه‌سازی کنید. Brain Monkey راه دوم را انتخاب می‌کند و آن را بسیار ساده می‌کند.

سه ویژگی کلیدی Brain Monkey عبارتند از:

  • بدون نیاز به وردپرس: تست‌ها بدون بارگذاری وردپرس اجرا می‌شوند.
  • بدون نیاز به پایگاه داده: هیچ اتصال MySQL لازم نیست.
  • سرعت بالا: اجرای تست‌ها در میلی‌ثانیه به‌جای ثانیه.

این ویژگی‌ها، Brain Monkey را به یکی از محبوب‌ترین ابزارهای تست در اکوسیستم وردپرس تبدیل کرده است. برای درک عمیق‌تر ساختار تست در وردپرس، تست و دیباگ پروژه‌های توسعه وردپرس را ببینید.

Brain Monkey یک «پل» است: کد شما را از وردپرس جدا می‌کند تا بتوانید منطق آن را مستقل تست کنید. این جداسازی، نه فقط سرعت، بلکه کیفیت معماری را هم بهبود می‌بخشد.

چرا Brain Monkey برای وردپرس ضروری است؟

در اکوسیستم وردپرس، تست‌نویسی به‌طور سنتی ضعیف بوده است. سه دلیل اصلی برای این ضعف وجود دارد: پیچیدگی راه‌اندازی WordPress Test Suite، وابستگی شدید کد به توابع سراسری، و کندی اجرای تست‌ها. Brain Monkey هر سه مشکل را حل می‌کند.

در پروژه‌های واقعی که بازبینی کرده‌ام، تفاوت بین پروژه‌هایی که تست دارند و پروژه‌هایی که ندارند، در سه محور دیده می‌شود:

  • پایداری: پروژه‌های دارای تست، در برابر regression مقاوم‌تر هستند.
  • سرعت توسعه: تغییرات بدون ترس از شکستن انجام می‌شود.
  • مستندسازی: تست‌ها، رفتار مورد انتظار را مستند می‌کنند.

Brain Monkey این سه مزیت را بدون هزینه سنگین راه‌اندازی فراهم می‌کند. به‌جای اینکه برای هر تغییر کوچک، وردپرس و پایگاه داده را بارگذاری کنید، می‌توانید منطق کد را در محیطی سبک تست کنید. برای درک عمیق‌تر ساختار پروژه، ساختاردهی پروژه توسعه وردپرس را ببینید.

نکته مهم این است که Brain Monkey جایگزین WordPress Test Suite نیست، بلکه مکمل آن است. برای تست‌های integration که نیازمند وردپرس واقعی هستند، WordPress Test Suite لازم است. اما برای تست‌های unit که منطق خالص را بررسی می‌کنند، Brain Monkey کافی و مؤثرتر است. برای درک تفاوت این دو رویکرد، توسعه وردپرس با محیط لوکال را ببینید.

تفاوت Brain Monkey و WordPress Test Suite

ویژگیBrain MonkeyWordPress Test Suite
نیاز به وردپرسخیربله
نیاز به MySQLخیربله
سرعت اجرامیلی‌ثانیهثانیه
نوع تستUnitIntegration و Functional
شبیه‌سازی هوک‌هابلهنیاز نیست (واقعی است)
پیچیدگی راه‌اندازیکمزیاد

جمع‌بندی این مقایسه ساده است: اگر منطق کد شما قابل جداسازی از وردپرس است، Brain Monkey انتخاب درست است. اگر کد شما به رفتار واقعی وردپرس (مانند ذخیره‌سازی در پایگاه داده یا اجرای هوک‌ها) وابسته است، WordPress Test Suite لازم است. بسیاری از پروژه‌های حرفه‌ای، هر دو را در کنار هم استفاده می‌کنند. برای درک عمیق‌تر خطاهای کد، دیباگ کردن کدهای سفارشی وردپرس را ببینید.

Monkey Patching در PHP چگونه کار می‌کند؟

Monkey Patching یک تکنیک برنامه‌نویسی است که در آن رفتار یک تابع یا کلاس در زمان اجرا تغییر می‌کند. در PHP، توابع سراسری معمولاً غیرقابل تغییر هستند، اما کتابخانه Patchwork با استفاده از stream wrapper، امکان بازنویسی آن‌ها را فراهم می‌کند.

مکانیزم کار Patchwork به این شکل است:

  1. یک stream wrapper ثبت می‌شود که فایل‌های PHP را قبل از اجرا بازنویسی می‌کند.
  2. هر فراخوانی تابع سراسری، به یک تابع wrapper هدایت می‌شود.
  3. wrapper تصمیم می‌گیرد که تابع اصلی را فراخوانی کند یا یک نسخه شبیه‌سازی‌شده.

این مکانیزم، امکان شبیه‌سازی توابع وردپرس را بدون تغییر کد اصلی فراهم می‌کند. برای درک عمیق‌تر هوک‌های وردپرس که معمولاً شبیه‌سازی می‌شوند، هوک‌های وردپرس: قلب تپنده توسعه را ببینید.

نکته مهم این است که Patchwork فقط روی توابعی کار می‌کند که در فایل‌های PHP فراخوانی می‌شوند. اگر تابعی در extensionهای C نوشته شده باشد، Monkey Patching کار نمی‌کند. خوشبختانه، اکثر توابع وردپرس در PHP نوشته شده‌اند و قابل شبیه‌سازی هستند.

نصب و راه‌اندازی Brain Monkey

Brain Monkey از طریق Composer نصب می‌شود. ابتدا باید در فایل composer.json پروژه، آن را به‌عنوان وابستگی توسعه اضافه کنید:

composer require --dev brain/monkey

سپس در فایل bootstrap تست‌ها، Brain Monkey را راه‌اندازی کنید:

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Brain\Monkey\setupPatchwork;

setupPatchwork();

در فایل phpunit.xml، مسیر bootstrap را مشخص کنید:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php">
  <testsuites>
    <testsuite name="unit">
      <directory>tests/unit</directory>
    </testsuite>
  </testsuites>
</phpunit>

برای درک عمیق‌تر راه‌اندازی PHPUnit در وردپرس، PHP در وردپرس را ببینید.

شبیه‌سازی توابع وردپرس

Brain Monkey اجازه می‌دهد توابع وردپرس را شبیه‌سازی کنید. یک مثال ساده:

<?php
use Brain\Monkey;
use function Brain\Monkey\Functions\when;
use function Brain\Monkey\Functions\expect;

class MyPluginTest extends \PHPUnit\Framework\TestCase {
    public function setUp(): void {
        parent::setUp();
        Monkey\setUp();
    }

    public function tearDown(): void {
        Monkey\tearDown();
        parent::tearDown();
    }

    public function test_get_custom_option_returns_value() {
        when( 'get_option' )->justReturn( 'my_value' );

        $result = my_plugin_get_custom_option();

        $this->assertEquals( 'my_value', $result );
    }

    public function test_get_custom_option_is_called_once() {
        expect( 'get_option' )->once();

        my_plugin_get_custom_option();
    }
}

در این مثال، تابع get_option که یک تابع سراسری وردپرس است، شبیه‌سازی شده و مقدار مشخصی برمی‌گرداند. این یعنی تست شما بدون بارگذاری وردپرس اجرا می‌شود. برای درک عمیق‌تر توابع وردپرس، نحوه استفاده از توابع وردپرس در پروژه‌ها را ببینید.

شبیه‌سازی با پارامترهای مشخص

when( 'get_option' )->with( 'my_setting' )->justReturn( 'value' );
when( 'get_option' )->with( 'other_setting' )->justReturn( 42 );

این الگو اجازه می‌دهد برای هر پارامتر، پاسخ متفاوتی تعریف کنید.

شبیه‌سازی با توالی پاسخ‌ها

when( 'get_transient' )
    ->justReturn( 'first_value' )
    ->justReturn( 'second_value' );

این الگو برای تست سناریوهای caching مفید است.

شبیه‌سازی هوک‌های وردپرس

Brain Monkey یک API اختصاصی برای شبیه‌سازی هوک‌های وردپرس دارد که در namespace Brain\Monkey\Actions و Brain\Monkey\Filters قرار دارد.

شبیه‌سازی اکشن‌ها

use Brain\Monkey\Actions\expect;

expect( 'init' )->once();
expect( 'wp_loaded' )->never();

شبیه‌سازی فیلترها

use Brain\Monkey\Filters\apply_filters;

apply_filters( 'my_filter' )->with( 'value' )->andReturn( 'modified' );

در کد افزونه:

$value = apply_filters( 'my_filter', 'value' );
// $value برابر 'modified' خواهد بود

این الگو، امکان تست رفتار کد در شرایط مختلف فیلترها را فراهم می‌کند. برای درک عمیق‌تر، آموزش استفاده از هوک‌های وردپرس برای توسعه‌دهندگان را ببینید.

شبیه‌سازی do_action

use Brain\Monkey\Actions\do_action;

do_action( 'my_custom_action' )->once();

// در کد افزونه:
do_action( 'my_custom_action', $data );

این الگو، تأیید می‌کند که اکشن موردنظر با پارامترهای درست فراخوانی شده است.

شبیه‌سازی درخواست‌های HTTP

یکی از پرکاربردترین سناریوها در افزونه‌های وردپرسی، شبیه‌سازی درخواست‌های HTTP است. Brain Monkey به‌سادگی این کار را ممکن می‌کند:

use function Brain\Monkey\Functions\when;

$response = [
    'response' => ['code' => 200],
    'body' => json_encode( ['status' => 'ok'] ),
];

when( 'wp_remote_get' )->justReturn( $response );
when( 'wp_remote_retrieve_body' )->justReturn( json_encode( ['status' => 'ok'] ) );

با این الگو، می‌توانید رفتار افزونه را در برابر پاسخ‌های موفق، خطا، timeout و کدهای HTTP مختلف تست کنید. برای درک عمیق‌تر، نوشتن کد PHP امن برای وردپرس را ببینید.

سناریوهای واقعی در افزونه‌های وردپرسی

در پروژه‌های واقعی، Brain Monkey در چند سناریو بیشترین ارزش را ایجاد می‌کند:

سناریو ۱: تست منطق سفارشی

اگر افزونه شما یک الگوریتم سفارشی دارد (مانند محاسبه قیمت، امتیازدهی، یا تبدیل داده)، این منطق باید جدا از وردپرس تست شود. Brain Monkey این جداسازی را ممکن می‌کند.

سناریو ۲: تست رفتار در برابر فیلترها

بسیاری از افزونه‌ها رفتار خود را بر اساس فیلترهای وردپرس تغییر می‌دهند. Brain Monkey امکان تست این رفتار را فراهم می‌کند:

apply_filters( 'myplugin_price' )->with( 100 )->andReturn( 90 );

$final = myplugin_calculate_price( 100 );
$this->assertEquals( 90, $final );

سناریو ۳: تست تنظیمات افزونه

when( 'get_option' )->with( 'myplugin_settings' )->justReturn( [
    'enabled' => true,
    'threshold' => 50,
] );

$this->assertTrue( myplugin_is_enabled() );

سناریو ۴: تست نقش‌ها و دسترسی‌ها

when( 'current_user_can' )->with( 'manage_options' )->justReturn( true );

$this->assertTrue( myplugin_user_can_manage() );

این الگوها، امکان تست جامع افزونه‌ها را بدون راه‌اندازی وردپرس فراهم می‌کنند. برای درک عمیق‌تر ساختار افزونه، ساختار استاندارد افزونه وردپرس را ببینید.

ادغام Brain Monkey در CI/CD

یکی از بزرگ‌ترین مزایای Brain Monkey، امکان اجرای تست‌ها در CI/CD (Continuous Integration/Continuous Deployment - یکپارچه‌سازی و استقرار مداوم) است. بدون وابستگی به MySQL و وردپرس، تست‌ها در هر محیطی اجرا می‌شوند.

یک نمونه GitHub Actions:

name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
      - run: composer install --no-interaction
      - run: vendor/bin/phpunit

این workflow در چند ثانیه اجرا می‌شود، در حالی که با WordPress Test Suite ممکن بود چند دقیقه طول بکشد. برای درک عمیق‌تر، CI/CD برای پروژه‌های وردپرسی را ببینید.

محدودیت‌ها و چه زمانی از WordPress Test Suite استفاده کنیم؟

Brain Monkey ابزار قدرتمندی است، اما برای همه سناریوها مناسب نیست:

  • تست‌های integration: اگر می‌خواهید بررسی کنید که کد شما با وردپرس واقعی درست کار می‌کند، WordPress Test Suite لازم است.
  • تست پایگاه داده: Brain Monkey نمی‌تواند رفتار واقعی MySQL را شبیه‌سازی کند.
  • تست هوک‌های واقعی: در Brain Monkey، هوک‌ها شبیه‌سازی می‌شوند و رفتار واقعی آن‌ها بررسی نمی‌شود.
  • تست قالب: برای تست رندر قالب، نیازمند وردپرس واقعی هستید.
  • تست REST API: برای تست کامل endpointهای REST، WordPress Test Suite مناسب‌تر است.

بهترین رویکرد، استفاده ترکیبی است: ۷۰ درصد تست‌های unit با Brain Monkey، و ۳۰ درصد تست‌های integration با WordPress Test Suite. برای درک عمیق‌تر خطاهای کد، اشتباهات رایج در کدنویسی وردپرس را ببینید.

اشتباهات رایج در استفاده از Brain Monkey

  • فراموش کردن Monkey\setUp() و Monkey\tearDown(): بدون این دو، شبیه‌سازی‌ها بین تست‌ها نشت می‌کنند.
  • شبیه‌سازی توابعی که در C نوشته شده‌اند: Patchwork روی این توابع کار نمی‌کند.
  • استفاده از expect() بدون تعریف رفتار: تست شکست می‌خورد.
  • نادیده گرفتن with(): بدون آن، همه فراخوانی‌ها با هر پارامتری پذیرفته می‌شوند.
  • تست بیش از حد: نوشتن تست برای هر خط کد، زمان‌بر و بی‌فایده است.
  • عدم جداسازی منطق: اگر منطق کد شما به‌شدت با وردپرس درهم‌تنیده است، Brain Monkey کمکی نمی‌کند.
  • نادیده گرفتن حالت‌های خطا: باید رفتار در برابر خطا، timeout و پاسخ نامعتبر نیز تست شود.
  • اعتماد به شبیه‌سازی برای همه چیز: شبیه‌سازی، جایگزین تست integration نیست.

برای مرور خطاهای مشابه، دیباگ کردن کدهای سفارشی وردپرس را ببینید.

پرسش‌های پرتکرار درباره Brain Monkey

آیا Brain Monkey جایگزین WordPress Test Suite است؟ نه، مکمل آن است. برای تست unit از Brain Monkey و برای integration از WordPress Test Suite استفاده کنید.

آیا Brain Monkey روی همه توابع وردپرس کار می‌کند؟ روی توابعی که در PHP نوشته شده‌اند بله، اما روی توابع extensionهای C خیر.

چطور Brain Monkey را نصب کنم؟ با Composer: composer require --dev brain/monkey. برای مراحل کامل، راه‌اندازی PHPUnit در وردپرس را ببینید.

آیا Brain Monkey در CI/CD کار می‌کند؟ بله، و یکی از بزرگ‌ترین مزایای آن است. برای مرور گزینه‌ها، CI/CD برای پروژه‌های وردپرسی را ببینید.

آیا Brain Monkey سرعت تست را افزایش می‌دهد؟ بله، به‌طور قابل توجه. تست‌ها از ثانیه به میلی‌ثانیه کاهش می‌یابند.

آیا استفاده از Brain Monkey نیازمند تغییر کد است؟ نه، Brain Monkey کد شما را تغییر نمی‌دهد. فقط توابع سراسری را در زمان تست شبیه‌سازی می‌کند.

برای مطالعه بیشتر درباره مفاهیم پایه، صفحه Mock object در ویکی‌پدیا مفید است.

خط پایان

Brain Monkey یکی از آن ابزارهایی است که پس از استفاده، دیگر نمی‌توان بدون آن کار کرد. این کتابخانه، موانع تست‌نویسی در وردپرس را — کندی، وابستگی به پایگاه داده، و پیچیدگی راه‌اندازی — برمی‌دارد و تست‌نویسی را به یک بخش طبیعی از توسعه تبدیل می‌کند. اگر روی افزونه یا کتابخانه‌ای کار می‌کنید که منطق آن قابل جداسازی از وردپرس است، Brain Monkey یکی از مؤثرترین سرمایه‌گذاری‌هایی است که می‌توانید انجام دهید. اگر افزونه شما تست ندارد، همین امروز با یک تست ساده شروع کنید.

اگر در پروژه‌ای Brain Monkey را پیاده کرده‌اید یا با چالش‌هایی روبه‌رو شده‌اید، تجربه خود را در دیدگاه‌ها بنویسید؛ به‌خصوص اگر سناریوی خاصی داشته‌اید که حل آن برای دیگران مفید است، این اطلاعات برای خواننده بعدی بسیار ارزشمند است.