আপনি যদি কখনও দেখে থাকেন যে একটি প্লাগইন প্রথমে স্থানীয়ভাবে "কাজ" করছিল এবং তারপর একটি ছোটখাটো আপডেটের পর নীরবে নষ্ট হয়ে গেছে, তাহলে বুঝবেন এটি আপনার জন্য একটি নতুন অভিজ্ঞতা। ওয়ার্ডপ্রেস সংস্করণ ৬.৯.৪-এ, সমস্যাটি খুব কমই কোনো একটি নির্দিষ্ট লাইন থেকে উদ্ভূত হয়। এর কারণ হলো পুনরাবৃত্তিযোগ্য পরীক্ষার অভাব, এবং বিশেষ করে বিশুদ্ধ লজিক ও ওয়ার্ডপ্রেস ইন্টিগ্রেশনের মধ্যে পৃথকীকরণের অভাব।
আমরা যা নির্মাণ করতে যাচ্ছি
আপনাকে PHP 8.1+ এবং WordPress 6.9.4+ এর সাথে সামঞ্জস্যপূর্ণ একটি ওয়ার্ডপ্রেস প্লাগইনের জন্য দুটি স্তর সহ একটি আধুনিক পরীক্ষামূলক পরিবেশ (এপ্রিল ২০২৬) স্থাপন করতে হবে:
- ইউনিট পরীক্ষা (দ্রুত): ওয়ার্ডপ্রেস লোড না করেই আপনার পিএইচপি লজিক পরীক্ষা করুন।
- ইন্টিগ্রেশন পরীক্ষা (বাস্তবসম্মত): ওয়ার্ডপ্রেস লোড করুন এবং এর মাধ্যমে হুক, রোল/ক্যাপাবিলিটি, ননস এবং ডিবি ইন্টারঅ্যাকশন যাচাই করুন।
WP_UnitTestCase.
চূড়ান্ত ফলাফল: একটি পরীক্ষাযোগ্য আর্কিটেকচার (সার্ভিসেস + সিম্পল ডিআই) সহ একটি নমুনা প্লাগইন “বিপিসিএবি ডেমো”, একটি পিএইচপিইউনিট স্যুট, এবং একটি গিটহাব অ্যাকশনস পাইপলাইন যা একটি পিএইচপি/ডব্লিউপি ম্যাট্রিক্সের উপর পরীক্ষা চালায়।
অবশেষে, আপনি জানতে পারবেন:
- ওয়ার্ডপ্রেস ছাড়াই লজিক পরীক্ষাযোগ্য করে একটি প্লাগইনের কাঠামো তৈরি করা।
- কম্পোজারের মাধ্যমে ওয়ার্ডপ্রেস টেস্ট স্যুটটি সঠিকভাবে ইনস্টল ও কনফিগার করুন।
- নির্ভরযোগ্য টেস্ট (ইউনিট ও ইন্টিগ্রেশন) লিখুন যা ত্রুটিপূর্ণ নয়।
- ম্যাট্রিক্স এবং ক্যাশের সাহায্যে CI এক্সিকিউশন স্বয়ংক্রিয় করুন।
দ্রুত সারসংক্ষেপ
- আমরা আলাদা হয়ে যাই ডোমেইন (বিশুদ্ধ পিএইচপি) এবং অবকাঠামো (WP, DB, REST, অ্যাডমিন হুকস)।
- সুরকার পরিচালনা করে অটোলোড এবং উন্নয়ন নির্ভরতা (
phpunit/phpunit). - দুটি PHPUnit স্যুট: একক (WP ছাড়া) এবং ইন্টিগ্রেশন (WP সহ)।
- ইন্টিগ্রেশন বুটস্ট্র্যাপ এর মাধ্যমে ওয়ার্ডপ্রেস লোড করে। WP টেস্ট স্যুট এবং পরীক্ষার ডাটাবেস কনফিগার করে।
- CI-তে, আমরা একটি ম্যাট্রিক্স কার্যকর করি। পিএইচপি ৮.১/৮.২/৮.৩ + WP 6.9.4 (এবং সম্ভবত) রাত্রিকালীন (যদি আপনি ঝুঁকি নিয়ে বাঁচতে পছন্দ করেন)।
কখন এই সমাধানটি ব্যবহার করবেন
- আপনি একটি “ব্যবসায়িকভাবে গুরুত্বপূর্ণ” প্লাগইন (ই-কমার্স, মেম্বারশিপ, এসইও, ফর্ম, সিনক্রোনাইজেশন) রক্ষণাবেক্ষণ করেন।
- ওয়ার্ডপ্রেস/পিএইচপি আপডেট করার সময় আপনি ত্রুটির সম্মুখীন হচ্ছেন।
- আপনারা একটি দল হিসেবে উন্নতি করেন এবং এমন পিআর চান যা সহজে ভাঙে না।
- আপনি জটিল হুক (অগ্রাধিকার, ক্রমসঞ্চয়ী ফিল্টার, শর্টকোড, REST) ব্যবহার করছেন।
- আপনি আমানতের জন্য লক্ষ্য করছেন WordPress.org এবং আপনি ন্যূনতম কঠোরতা চান।
কখন এই সমাধানটি ব্যবহার করা উচিত নয়
- আপনার “প্লাগইন” হলো একটি স্নিপেটস প্লাগইনে পেস্ট করা মাত্র ১৫ লাইনের একটি সাধারণ কোড স্নিপেট (এবং এমনকি সেক্ষেত্রেও: একটি ইউনিট টেস্ট উপকারী হতে পারে, কিন্তু এর জন্য বিনিয়োগটি অসামঞ্জস্যপূর্ণ)।
- আপনি এমন একটি এককালীন প্রকল্পে কাজ করছেন যার কোনো রক্ষণাবেক্ষণের প্রয়োজন নেই (ওয়ার্ডপ্রেসে এটি বিরল, তবে এমনটা ঘটে থাকে)।
- আপনি কম্পোজার ব্যবহার করতে রাজি নন: অটোলোড এবং ডেভ ডিপেন্ডেন্সি ছাড়া, আপনি শুধু ঘাঁটাঘাঁটি করে সময় নষ্ট করবেন।
- আপনার কোনো বিচ্ছিন্ন পরিবেশ (ডকার/টেস্ট ডিবি) নেই। ব্যাকআপ ছাড়া প্রোডাকশনে পরীক্ষা করতে গেলে এমনটা হতে দেখেছি, এবং এর পরিণতি খারাপ হয়।
শুরু করার আগে (পূর্বশর্তসমূহ)
সংস্করণ এবং পরিবেশ
- ওয়ার্ডপ্রেস ৬.৯.৪ (লক্ষ্য) বা তার পরবর্তী সংস্করণ।
- পিএইচপি সর্বনিম্ন ৮.১ (প্রস্তাবিত), ৮.২/৮.৩ হলে চলবে।
- সুরকার : ২.x.
- মাইএসকিউএল / MariaDB পরীক্ষার জন্য নিবেদিত একটি ডাটাবেস (যেমন:
wp_tests).
ব্যাকআপ এবং বিচ্ছিন্নকরণ
- নির্দেশ করবেন না। jamais আপনার প্রোডাকশন ডিবি-তে টেস্ট কনফিগারেশনটি যুক্ত করুন।
- সম্ভব হলে পরীক্ষার উদ্দেশ্যে একটি সীমিত ডেটাবেস ব্যবহারকারী তৈরি করুন।
- গিট রিপোজিটরিতে কাজ: আপনাকে কনফিগারেশন ফাইল এবং স্ক্রিপ্ট নিয়ে কাজ করতে হবে।
দরকারী সরকারি সম্পদ
- WP-CLI (ডেভেলপার রিসোর্স) (দরকারী কিন্তু ঐচ্ছিক)।
- @wordpress/scripts (যদি আপনি JS-ও পরীক্ষা করেন, তবে তা এখানকার মূল আলোচনার বাইরে)।
- PHPUnit ডকুমেন্টেশন.
- ওয়ার্ডপ্রেস কোর হ্যান্ডবুক: পিএইচপিইউনিট.
- ওয়ার্ডপ্রেস-ডেভেলপ রিপোজিটরি (WP টেস্ট স্যুটের উৎস)।
ধাপ ১: একটি পরীক্ষাযোগ্য প্লাগইন তৈরি করুন (স্কেলেটন + অটোলোড)
আসল সুবিধাটা এখান থেকেই আসে: যদি আপনার লজিক অ্যানোনিমাস কলব্যাকে আটকে থাকে, তাহলে আপনি আপনার কোড পরীক্ষা করার পরিবর্তে "ওয়ার্ডপ্রেস পরীক্ষা" করবেন। আমি সাধারণত আলাদা করি:
- src/ডোমেইন বিশুদ্ধ যুক্তি (ইউনিট পরীক্ষা)।
- src/অবকাঠামো ওয়ার্ডপ্রেস (হুকস, অপশনস, রেস্ট, অ্যাডমিন)।
- src/প্লাগইন বুটস্ট্র্যাপ এবং সার্ভিস রেজিস্ট্রেশন।
১) প্লাগইন ফোল্ডার তৈরি করুন
মধ্যে wp-content/plugins/তৈরি করুন:
bpcab-demo/bpcab-demo/bpcab-demo.phpbpcab-demo/src/bpcab-demo/tests/
২) প্রধান প্লাগইন ফাইল
তৈরি করুন wp-content/plugins/bpcab-demo/bpcab-demo.php :
<?php
/**
* Plugin Name: BPCAB Demo (Testable)
* Description: Plugin d'exemple pour tests unitaires + intégration WordPress.
* Version: 0.1.0
* Requires at least: 6.9
* Requires PHP: 8.1
*/
declare(strict_types=1);
if (!defined('ABSPATH')) {
exit;
}
// Autoload Composer (en dev, et aussi en prod si vous packez vendor/).
$autoload = __DIR__ . '/vendor/autoload.php';
if (file_exists($autoload)) {
require_once $autoload;
}
add_action('plugins_loaded', static function (): void {
// Bootstrap minimal. En vrai, je préfère une classe Plugin + container.
$plugin = new BpcabDemoPluginPlugin(__FILE__);
$plugin->boot();
});
৩) একটি প্লাগইন ক্লাস + একটি মিনি-কন্টেইনার
তৈরি করুন src/Plugin/Plugin.php :
<?php
declare(strict_types=1);
namespace BpcabDemoPlugin;
use BpcabDemoInfrastructureHooksHelloHook;
use BpcabDemoPluginContainerContainer;
final class Plugin
{
private string $pluginFile;
private Container $container;
public function __construct(string $pluginFile)
{
$this->pluginFile = $pluginFile;
$this->container = new Container();
}
public function boot(): void
{
// Enregistrement des services.
$this->container->set(HelloHook::class, function (): HelloHook {
return new HelloHook();
});
// Activation des intégrations WP.
$this->container->get(HelloHook::class)->register();
}
}
তৈরি করুন src/Plugin/Container/Container.php :
<?php
declare(strict_types=1);
namespace BpcabDemoPluginContainer;
use RuntimeException;
final class Container
{
/** @var array<string, callable> */
private array $factories = [];
/** @var array<string, object> */
private array $instances = [];
/**
* @param callable():object $factory
*/
public function set(string $id, callable $factory): void
{
$this->factories[$id] = $factory;
}
public function get(string $id): object
{
if (isset($this->instances[$id])) {
return $this->instances[$id];
}
if (!isset($this->factories[$id])) {
throw new RuntimeException("Service introuvable: {$id}");
}
$instance = ($this->factories[$id])();
$this->instances[$id] = $instance;
return $instance;
}
}
৪) বিশুদ্ধ যুক্তির একটি উদাহরণ + একটি WP হুক
তৈরি করুন src/Domain/Greeting.php :
<?php
declare(strict_types=1);
namespace BpcabDemoDomain;
final class Greeting
{
public function message(string $name): string
{
$name = trim($name);
if ($name === '') {
return 'Bonjour !';
}
// Cas réel : éviter les espaces multiples, et limiter la taille.
$name = preg_replace('/s+/', ' ', $name) ?? $name;
$name = mb_substr($name, 0, 60);
return "Bonjour {$name} !";
}
}
তৈরি করুন src/Infrastructure/Hooks/HelloHook.php :
<?php
declare(strict_types=1);
namespace BpcabDemoInfrastructureHooks;
use BpcabDemoDomainGreeting;
final class HelloHook
{
public function register(): void
{
add_shortcode('bpcab_hello', [$this, 'shortcode']);
}
/**
* @param array<string,mixed> $atts
*/
public function shortcode(array $atts = []): string
{
$atts = shortcode_atts(
[
'name' => '',
],
$atts,
'bpcab_hello'
);
$greeting = new Greeting();
// Sécurité : sortie échappée.
return esc_html($greeting->message((string) $atts['name']));
}
}
প্রত্যাশিত ফলাফল
প্লাগইনটি সক্রিয় করুন এক্সটেনশানগুলি → ইনস্টল করা এক্সটেনশনএকটি পৃষ্ঠায় যোগ করুন:
[bpcab_hello name="Marie Curie"]
আপনাকে অবশ্যই “হ্যালো মারি কুরি!” দেখতে হবে।
ধাপ ২: PHPUnit ও WordPress টেস্ট স্যুট (Composer) ইনস্টল করুন।
ওয়ার্ডপ্রেসে একটি চিরাচরিত বিভ্রান্তি দেখা দেয়: “আমি PHPUnit ইনস্টল করেছি, তাই আমি পরীক্ষা করতে পারি।” না। ইন্টিগ্রেশন টেস্টিংয়ের জন্য আপনার WP টেস্ট স্যুটও (ফাইলগুলো) প্রয়োজন। includes/bootstrap.phpকারখানা ইত্যাদি)।
১) কম্পোজার শুরু করুন
প্লাগইন ফোল্ডারে:
cd wp-content/plugins/bpcab-demo
composer init
আমি আপনাকে একটি প্যাকেজ নামের ধরণ প্রবেশ করানোর পরামর্শ দিচ্ছি। vendor/bpcab-demoএবং সংজ্ঞায়িত করতে src/ উৎস হিসেবে
২) PHPUnit এবং PSR-4 অটোলোডিং যোগ করুন
তৈরি/সম্পাদনা করুন composer.json :
{
"name": "vendor/bpcab-demo",
"type": "wordpress-plugin",
"require": {
"php": ">=8.1"
},
"require-dev": {
"phpunit/phpunit": "^11.0"
},
"autoload": {
"psr-4": {
"BpcabDemo\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"BpcabDemo\Tests\": "tests/"
}
},
"scripts": {
"test:unit": "phpunit -c phpunit.unit.xml",
"test:integration": "phpunit -c phpunit.integration.xml"
}
}
তারপর :
composer install
composer dump-autoload
৩) ওয়ার্ডপ্রেস টেস্ট স্যুটটি সংগ্রহ করুন
আপনার কাছে বেশ কয়েকটি পদ্ধতি রয়েছে। ২০২৬ সালে, সবচেয়ে সহজ পদ্ধতিটিই থাকছে:
- ক্লোন ওয়ার্ডপ্রেস-ডেভেলপ আপনার মেশিনের কোথাও,
- তার ফাইল ব্যবহার করুন
tests/phpunitফলো-আপ পরীক্ষা হিসেবে।
উদাহরণ (পরিবর্তনযোগ্য):
mkdir -p ~/wp-tests
cd ~/wp-tests
git clone --depth=1 https://github.com/WordPress/wordpress-develop.git
এরপর আপনি পাবেন:
~/wp-tests/wordpress-develop/tests/phpunit~/wp-tests/wordpress-develop/src(ডব্লিউপি কোর “বিকাশযোগ্য”)
PHPUnit কোর-সাইড পদ্ধতির অফিসিয়াল উৎস: কোর হ্যান্ডবুক: স্বয়ংক্রিয় টেস্টিং / পিএইচপিইউনিট.
ধাপ ৩: টেস্ট বুটস্ট্র্যাপ লিখুন এবং পরিবেশকে বিচ্ছিন্ন করুন।
আমরা যাচ্ছি তৈরি দুটি PHPUnit কনফিগারেশন:
- একক ওয়ার্ডপ্রেস নেই, দ্রুত, ডেটাবেস নেই।
- ইন্টিগ্রেশন ওয়ার্ডপ্রেস ডেটাবেস লোড ও টেস্ট করুন।
১) PHPUnit কনফিগারেশন “unit”
তৈরি করুন phpunit.unit.xml প্লাগইনের মূলে:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="tests/bootstrap-unit.php"
colors="true"
failOnRisky="true"
failOnWarning="true"
cacheDirectory=".phpunit.cache/unit"
>
<testsuites>
<testsuite name="unit">
<directory suffix="Test.php">tests/unit</directory>
</testsuite>
</testsuites>
<php>
<ini name="error_reporting" value="-1"/>
</php>
</phpunit>
তৈরি করুন tests/bootstrap-unit.php :
<?php
declare(strict_types=1);
// Bootstrap minimal pour tests unitaires : autoload uniquement.
$autoload = dirname(__DIR__) . '/vendor/autoload.php';
if (!file_exists($autoload)) {
fwrite(STDERR, "Autoload introuvable. Lancez 'composer install'.n");
exit(1);
}
require_once $autoload;
2) PHPUnit “integration” কনফিগার করুন
তৈরি করুন phpunit.integration.xml :
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="tests/bootstrap-integration.php"
colors="true"
failOnRisky="true"
failOnWarning="true"
cacheDirectory=".phpunit.cache/integration"
>
<testsuites>
<testsuite name="integration">
<directory suffix="Test.php">tests/integration</directory>
</testsuite>
</testsuites>
<php>
<ini name="error_reporting" value="-1"/>
<!-- Paramètres DB : ne mettez jamais la prod ici -->
<env name="WP_TESTS_DB_NAME" value="wp_tests"/>
<env name="WP_TESTS_DB_USER" value="root"/>
<env name="WP_TESTS_DB_PASS" value=""/>
<env name="WP_TESTS_DB_HOST" value="127.0.0.1"/>
<!-- Chemins vers wordpress-develop (à adapter à votre machine) -->
<env name="WP_DEVELOP_DIR" value="/home/vous/wp-tests/wordpress-develop"/>
</php>
</phpunit>
তৈরি করুন tests/bootstrap-integration.php :
<?php
declare(strict_types=1);
/**
* Bootstrap d'intégration WordPress.
* Hypothèse : vous avez cloné wordpress-develop et indiqué WP_DEVELOP_DIR.
*/
$autoload = dirname(__DIR__) . '/vendor/autoload.php';
if (!file_exists($autoload)) {
fwrite(STDERR, "Autoload introuvable. Lancez 'composer install'.n");
exit(1);
}
require_once $autoload;
$developDir = getenv('WP_DEVELOP_DIR');
if (!$developDir) {
fwrite(STDERR, "WP_DEVELOP_DIR manquant. Configurez-le dans phpunit.integration.xml.n");
exit(1);
}
$testsDir = rtrim($developDir, '/\') . '/tests/phpunit';
if (!is_dir($testsDir)) {
fwrite(STDERR, "Dossier tests WordPress introuvable: {$testsDir}n");
exit(1);
}
// Variables attendues par la WP test suite.
$_tests_dir = $testsDir;
// Charge les fonctions utilitaires de la suite.
require_once $_tests_dir . '/includes/functions.php';
/**
* Charger le plugin avant que WordPress ne finisse son bootstrap de tests.
* C'est le point standard (muplugins_loaded) utilisé par la suite.
*/
tests_add_filter('muplugins_loaded', static function (): void {
require dirname(__DIR__) . '/bpcab-demo.php';
});
// Démarre WordPress pour les tests.
require_once $_tests_dir . '/includes/bootstrap.php';
প্রত্যাশিত ফলাফল
এই পর্যায়ে, টেস্টগুলো চালালেও কিছুই পাওয়া যাবে না (কোনো টেস্ট ফাইল থাকবে না), কিন্তু:
composer test:unit
অন্তত PHPUnit চালু করতে হবে।
ধাপ ৪: প্রকৃত ইউনিট টেস্ট লিখুন (ওয়ার্ডপ্রেস লোড না করে)
আমরা পরীক্ষা করছি BpcabDemoDomainGreetingএই পরীক্ষাটি দ্রুত, সুনির্দিষ্ট এবং WP কোরের উপর নির্ভরশীল নয়।
১) ফোল্ডার এবং পরীক্ষাটি তৈরি করুন
তৈরি করুন tests/unit/GreetingTest.php :
<?php
declare(strict_types=1);
namespace BpcabDemoTestsUnit;
use BpcabDemoDomainGreeting;
use PHPUnitFrameworkTestCase;
final class GreetingTest extends TestCase
{
public function testMessageSansNomRetourneUneFormeCourte(): void
{
$greeting = new Greeting();
$this->assertSame('Bonjour !', $greeting->message(''));
$this->assertSame('Bonjour !', $greeting->message(' '));
}
public function testMessageNormaliseLesEspaces(): void
{
$greeting = new Greeting();
$this->assertSame('Bonjour Ada Lovelace !', $greeting->message('Ada Lovelace'));
}
public function testMessageLimiteLaLongueurPourEviterDesSortiesAbsurdes(): void
{
$greeting = new Greeting();
$name = str_repeat('A', 1000);
$result = $greeting->message($name);
$this->assertStringStartsWith('Bonjour ', $result);
$this->assertStringEndsWith(' !', $result);
// "Bonjour " (8) + 60 + " !" (2) = 70
$this->assertSame(70, mb_strlen($result));
}
}
২) ইউনিট টেস্টগুলো চালান
composer test:unit
প্রত্যাশিত ফলাফল
আপনার একটি সবুজ ক্রম পাওয়া উচিত। যদি আপনি "ক্লাস পাওয়া যায়নি" এর মতো কোনো ত্রুটি পান, তাহলে এর কারণ প্রায় সবসময়ই হলো:
- ভুল PSR-4 অটোলোড
composer.json, - তুমি ভুলে গেছো
composer dump-autoload, - আপনি ফাইলটি ভুল ফোল্ডারে রেখেছেন।
ধাপ ৫: ওয়ার্ডপ্রেস ইন্টিগ্রেশন টেস্ট (WP_UnitTestCase)
এখন আমরা যাচাই করে দেখব যে শর্টকোডটি সঠিকভাবে নিবন্ধিত হয়েছে এবং রেন্ডারিংও সঠিক আছে। এই পর্যায়ে আমরা ওয়ার্ডপ্রেস লোড করি, তাই এটি ধীরগতির হয়, কিন্তু এর মাধ্যমে ‘আসল’ রিগ্রেশনগুলো ধরা পড়ে।
১) একটি ইন্টিগ্রেশন টেস্ট তৈরি করুন
তৈরি করুন tests/integration/ShortcodeHelloTest.php :
<?php
declare(strict_types=1);
namespace BpcabDemoTestsIntegration;
use WP_UnitTestCase;
final class ShortcodeHelloTest extends WP_UnitTestCase
{
public function testShortcodeEstEnregistre(): void
{
// Le plugin est chargé via bootstrap-integration.php.
global $shortcode_tags;
$this->assertIsArray($shortcode_tags);
$this->assertArrayHasKey('bpcab_hello', $shortcode_tags);
}
public function testShortcodeRendLeTexteAttendu(): void
{
$html = do_shortcode('[bpcab_hello name="Marie Curie"]');
// esc_html() est appliqué, donc pas de HTML.
$this->assertSame('Bonjour Marie Curie !', $html);
}
}
২) ইন্টিগ্রেশন টেস্টগুলো চালান
composer test:integration
প্রত্যাশিত ফলাফল
যদি পরীক্ষার ডাটাবেসটি অ্যাক্সেসযোগ্য হয় এবং যে WP_DEVELOP_DIR সঠিক হলে, আপনি একটি সবুজ ক্রম পাবেন।
যদি আপনি “ডেটাবেস সংযোগ স্থাপনে ত্রুটি” (Error establishing a database connection) দেখতে পান, তবে এলোমেলোভাবে এটি ঠিক করার চেষ্টা করবেন না। প্রথমে, পরীক্ষা করে দেখুন যে:
- লা বেস
wp_testsবিদ্যমান, - ডিবি ব্যবহারকারীর অধিকার আছে,
- আপনি রাখেননি
localhostযখন আপনার MySQL শুনছে127.0.0.1(অথবা কনফিগারেশনের উপর নির্ভর করে এর উল্টোটাও হতে পারে)।
ধাপ ৬: হুক, ফিল্টার, ক্যাপাবিলিটি এবং ননস পরীক্ষা করুন।
প্রোডাকশনে যে টেস্টগুলো সবচেয়ে বেশি বাগ ধরে, সেগুলো হলো: যেগুলো যাচাই করে যে আপনি আপনার হুকগুলো সঠিক জায়গায়, সঠিক প্রায়োরিটিতে যুক্ত করেছেন এবং নিরাপত্তা (ননস/ক্যাপাবিলিটি) মেনে চলা হচ্ছে।
১) একটি সুরক্ষিত অ্যাডমিন অ্যাকশন যোগ করুন (উদাহরণ)
আমরা একটি খুব সাধারণ অ্যাডমিন অ্যাকশন এন্ডপয়েন্ট যোগ করি: এটি একটি অপশন আপডেট করে, কিন্তু শুধুমাত্র অ্যাডমিনদের জন্য এবং ননস (nonce) সহ।
তৈরি করুন src/Infrastructure/Admin/SettingsAction.php :
<?php
declare(strict_types=1);
namespace BpcabDemoInfrastructureAdmin;
final class SettingsAction
{
public const NONCE_ACTION = 'bpcab_demo_save';
public const OPTION_KEY = 'bpcab_demo_enabled';
public function register(): void
{
add_action('admin_post_bpcab_demo_save', [$this, 'handle']);
}
public function handle(): void
{
if (!current_user_can('manage_options')) {
wp_die('Accès refusé', 403);
}
check_admin_referer(self::NONCE_ACTION);
$enabled = isset($_POST['enabled']) && $_POST['enabled'] === '1';
update_option(self::OPTION_KEY, $enabled ? '1' : '0');
wp_safe_redirect(admin_url('options-general.php?page=bpcab-demo'));
exit;
}
}
প্লাগ ইন করুন src/Plugin/Plugin.php :
<?php
// ... (extrait) ...
use BpcabDemoInfrastructureAdminSettingsAction;
// ... dans boot() ...
$this->container->set(SettingsAction::class, function (): SettingsAction {
return new SettingsAction();
});
$this->container->get(SettingsAction::class)->register();
২) পরীক্ষার ক্ষমতা + ননস
তৈরি করুন tests/integration/SettingsActionTest.php :
<?php
declare(strict_types=1);
namespace BpcabDemoTestsIntegration;
use BpcabDemoInfrastructureAdminSettingsAction;
use WP_UnitTestCase;
final class SettingsActionTest extends WP_UnitTestCase
{
public function setUp(): void
{
parent::setUp();
update_option(SettingsAction::OPTION_KEY, '0');
}
public function tearDown(): void
{
// Nettoyage : évite les tests interdépendants.
delete_option(SettingsAction::OPTION_KEY);
parent::tearDown();
}
public function testActionRefuseSansCapacite(): void
{
$userId = self::factory()->user->create(['role' => 'subscriber']);
wp_set_current_user($userId);
$_POST = [
'_wpnonce' => wp_create_nonce(SettingsAction::NONCE_ACTION),
'enabled' => '1',
];
// wp_die() jette une exception dans la suite de tests WP.
$this->expectException(WPDieException::class);
do_action('admin_post_bpcab_demo_save');
}
public function testActionRefuseSansNonceValide(): void
{
$userId = self::factory()->user->create(['role' => 'administrator']);
wp_set_current_user($userId);
$_POST = [
'_wpnonce' => 'nonce_invalide',
'enabled' => '1',
];
$this->expectException(WPDieException::class);
do_action('admin_post_bpcab_demo_save');
}
public function testActionMetAJourOptionAvecNonceEtCapacite(): void
{
$userId = self::factory()->user->create(['role' => 'administrator']);
wp_set_current_user($userId);
$_POST = [
'_wpnonce' => wp_create_nonce(SettingsAction::NONCE_ACTION),
'enabled' => '1',
];
// On évite la redirection réelle en interceptant wp_redirect.
add_filter('wp_redirect', static function (string $location): string {
// On renvoie une URL neutre, mais on laisse WordPress continuer.
return $location;
});
try {
do_action('admin_post_bpcab_demo_save');
} catch (WPDieException $e) {
// Certains environnements de test peuvent convertir exit en die.
// On tolère, l'essentiel est l'état final.
}
$this->assertSame('1', get_option(SettingsAction::OPTION_KEY));
}
}
এই পরীক্ষাটি এমন একটি বিষয় তুলে ধরে যা আমি প্রায়শই সম্মুখীন হই: অ্যাডমিন হ্যান্ডলারগুলো অবশেষে exit() করেপরীক্ষার ক্ষেত্রে, এটিকে একটিতে অনুবাদ করা যেতে পারে wp_die অথবা ক্রম অনুসারে একটি ব্যতিক্রম। ধরণটি হলো: আপনি সঠিক আউটপুট স্ট্রিমের পরিবর্তে অবস্থা (বিকল্প, পোস্ট মেটা, ইত্যাদি) পরীক্ষা করেন।
দরকারী সরকারি সূত্র:
ধাপ ৭: ফ্যাক্টরি, ফিক্সচার, ডেটাবেস এবং পরিষ্করণ
যেসব ইন্টিগ্রেশন টেস্টে ত্রুটি দেখা দেয়, তার মূল কারণ প্রায়শই ডেটাবেসের অপরিচ্ছন্ন অবস্থা, অথবা এমন কোনো টেস্ট যা অন্য একটি টেস্টের উপর নির্ভরশীল। WP টেস্ট স্যুট ফ্যাক্টরি সরবরাহ করে, কিন্তু আপনাকে অবশ্যই নিয়মানুবর্তী থাকতে হবে:
- টেস্টে আপনার পোস্ট/ব্যবহারকারী/শর্তাবলী তৈরি করুন।
- ম্যানুয়াল বিকল্প/ট্রানজিয়েন্টগুলি পরিষ্কার করুন
tearDown(), - হার্ড-কোডেড আইডি ব্যবহার করবেন না।
উদাহরণ: একটি পোস্ট তৈরি করুন এবং একটি ফিল্টার পরীক্ষা করুন
চলুন এমন একটি ফিল্টার যোগ করি যা একটি অপশন অনুযায়ী পোস্টের শিরোনাম পরিবর্তন করবে।
তৈরি করুন src/Infrastructure/Hooks/TitlePrefixHook.php :
<?php
declare(strict_types=1);
namespace BpcabDemoInfrastructureHooks;
final class TitlePrefixHook
{
public const OPTION_PREFIX = 'bpcab_demo_title_prefix';
public function register(): void
{
add_filter('the_title', [$this, 'filterTitle'], 10, 2);
}
public function filterTitle(string $title, int $postId): string
{
$prefix = (string) get_option(self::OPTION_PREFIX, '');
$prefix = trim($prefix);
if ($prefix === '' || is_admin()) {
return $title;
}
// Évite de préfixer les titres vides.
if (trim($title) === '') {
return $title;
}
return $prefix . ' ' . $title;
}
}
প্লাগ ইন করুন Plugin.php অন্যান্য পরিষেবার মতোই
তৈরি করুন tests/integration/TitlePrefixHookTest.php :
<?php
declare(strict_types=1);
namespace BpcabDemoTestsIntegration;
use BpcabDemoInfrastructureHooksTitlePrefixHook;
use WP_UnitTestCase;
final class TitlePrefixHookTest extends WP_UnitTestCase
{
public function tearDown(): void
{
delete_option(TitlePrefixHook::OPTION_PREFIX);
parent::tearDown();
}
public function testPrefixAppliqueSurTitreFront(): void
{
update_option(TitlePrefixHook::OPTION_PREFIX, '[VIP]');
$postId = self::factory()->post->create([
'post_title' => 'Mon article',
'post_status' => 'publish',
]);
// Simule un contexte front.
$this->go_to(get_permalink($postId));
$this->assertFalse(is_admin());
$title = get_the_title($postId);
$this->assertSame('[VIP] Mon article', $title);
}
public function testNePrefixPasSiOptionVide(): void
{
update_option(TitlePrefixHook::OPTION_PREFIX, '');
$postId = self::factory()->post->create([
'post_title' => 'Mon article',
'post_status' => 'publish',
]);
$this->go_to(get_permalink($postId));
$this->assertSame('Mon article', get_the_title($postId));
}
}
এই পরীক্ষাটি আপনাকে নিম্নলিখিত বিষয়গুলো থেকে সুরক্ষা দেয়:
- একটি খারাপ হুক (অ্যাকশন এবং ফিল্টারের মধ্যে বিভ্রান্তি),
- এমন একটি অগ্রাধিকার যা ফলাফল পরিবর্তন করে (যদি অন্য কোনো প্লাগইনও এর আগে যুক্ত হয়),
- একটি অপরিবর্তিত অ্যাডমিন/ফ্রন্ট কনটেক্সট।
ধাপ ৮: গিটহাব অ্যাকশনস দিয়ে স্বয়ংক্রিয় করুন (ডব্লিউপি/পিএইচপি ম্যাট্রিক্স)
CI ছাড়া টেস্টিং 'ঐচ্ছিক'ই থেকে যায়। CI থাকলে, একটি রিগ্রেশন PR-এর ব্যর্থতায় পরিণত হয়। আর ঠিক তখনই এর সুফল পাওয়া শুরু হয়।
১) একটি গিটহাব অ্যাকশনস ওয়ার্কফ্লো যোগ করুন
তৈরি করুন .github/workflows/tests.yml (রিপোর মূলে, ভিতরে নয়) wp-content (যদি আপনার প্লাগইনটি একটি ডেডিকেটেড রিপোজিটরি হয়):
name: Tests
on:
push:
pull_request:
jobs:
phpunit:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ["8.1", "8.2", "8.3"]
wp: ["6.9.4"]
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wp_tests
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 -proot"
--health-interval=10s
--health-timeout=5s
--health-retries=10
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
coverage: none
- name: Cache Composer
uses: actions/cache@v4
with:
path: |
vendor
~/.composer/cache
key: composer-${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('composer.lock') }}
- name: Install dependencies
run: composer install --no-interaction --prefer-dist
- name: Checkout wordpress-develop
run: |
mkdir -p $HOME/wp-tests
cd $HOME/wp-tests
git clone --depth=1 --branch ${{ matrix.wp }} https://github.com/WordPress/wordpress-develop.git
- name: Run unit tests
run: composer test:unit
- name: Run integration tests
env:
WP_DEVELOP_DIR: ${{ env.HOME }}/wp-tests/wordpress-develop
WP_TESTS_DB_NAME: wp_tests
WP_TESTS_DB_USER: root
WP_TESTS_DB_PASS: root
WP_TESTS_DB_HOST: 127.0.0.1
run: composer test:integration
বাস্তবসম্মত নোট:
- ট্যাগ
6.9.4মধ্যেwordpress-developযদি কোনো শাখা/ট্যাগ মিলে যায়, তবে এটি বিদ্যমান থাকে। অন্যথায়, ব্যবহার করুন--branch 6.9অথবা একটি কমিট। আপনি যখন এটি পড়বেন, তখনকার মূল রিলিজ কৌশল অনুযায়ী এটিকে মানিয়ে নিন। - আপনি যদি WP nightly যোগ করেন, তবে সাময়িক ব্যর্থতা আশা করতে পারেন। আমি প্রায়শই গুরুত্বপূর্ণ প্লাগইনগুলোর জন্য এটিকে 'allowed failure' মোডে ব্যবহার করি।
তথ্যসূত্র: অফিসিয়াল কোর ডিপোজিট ওয়ার্ডপ্রেস-ডেভেলপ.
সম্পূর্ণ ফলাফল
আপনি যদি সবকিছু একবারে কপি করতে চান, তাহলে এখানে ন্যূনতম অ্যাসেম্বলিটি দেওয়া হলো (ইতিমধ্যে দেখানো ফাইলগুলো বাদে)। পাথগুলো পুনরায় যাচাই করে নিন।
গাছের কাঠামো
bpcab-demo/
bpcab-demo.php
composer.json
phpunit.unit.xml
phpunit.integration.xml
src/
Domain/
Greeting.php
Infrastructure/
Admin/
SettingsAction.php
Hooks/
HelloHook.php
TitlePrefixHook.php
Plugin/
Plugin.php
Container/
Container.php
tests/
bootstrap-unit.php
bootstrap-integration.php
unit/
GreetingTest.php
integration/
ShortcodeHelloTest.php
SettingsActionTest.php
TitlePrefixHookTest.php
দ্রুত কাস্টমাইজেশন
- একটি স্যুট যোগ করুন চুক্তি (সামঞ্জস্য পরীক্ষা) যদি আপনার প্লাগইনটি পাবলিক ফিল্টার প্রকাশ করে।
- যোগ পিএইচপিএসটান বিকাশের পর্যায়ে যদি আপনি টাইপগুলো লক করতে চান (যা “ডোমেইন/ইনফ্রাস্ট্রাকচার” আর্কিটেকচারের ক্ষেত্রে খুব কার্যকর)।
- পরিষেবা তৈরির কাজটি একটিতে স্থানান্তর করুন পরিষেবা প্রদানকারী যদি আপনার প্লাগইনটি বড় হয়।
Divi 5 / Elementor / Avada এর জন্য মানিয়ে নিন
পেজ বিল্ডার আপনাকে পরীক্ষা করতে বাধা দেয় না। মূল কথা হলো: আপনার পেজ পরীক্ষা করুন। যুক্তিবিদ্যা এবং আপনার ওয়ার্ডপ্রেস ইন্টিগ্রেশনবিল্ডারের UI নয় (যা মূলত e2e টেস্টিং-এর জন্য)।
দিভি ৫
- যদি আপনি একটি শর্টকোড প্রকাশ করেন যেমন
[bpcab_hello]Divi একটি “Code” বা “Text” মডিউলের মাধ্যমে এটি সহজেই ব্যবহার করে। - সুপারিশকৃত ইন্টিগ্রেশন টেস্ট: do_shortcode() (ইতিমধ্যে করা হয়েছে), এবং আপনি যদি অ্যাসেট যোগ করেন, পরীক্ষা করুন।
wp_enqueue_scripts(হুক + নির্ভরতা)।
Elementor
- জন্য একটি উইজেট প্রথা Elementorআমি উইজেট ক্লাস (ইনফ্রাস্ট্রাকচার) এবং একটি 'রেন্ডারার' সার্ভিস (ডোমেইন) আলাদা করি। রেন্ডারারটি একটি ইউনিট, এবং উইজেটটি ইন্টিগ্রেশনের সময় পরীক্ষা করা হয় (রেজিস্ট্রেশন হুকটি কল করা হয়েছে কিনা তা যাচাই করে)।
- আমি প্রায়শই একটি ব্যতিক্রমী পরিস্থিতি দেখি যেখানে উইজেট রেজিস্ট্রেশন কোডটি খুব তাড়াতাড়ি চলে যায়। প্রায়োরিটি পরীক্ষা করুন
elementor/widgets/register(অথবা এলিমেন্টর সংস্করণ অনুযায়ী সমতুল্য হুক)।
আভাদা (ফিউশন বিল্ডার)
- একই যুক্তি প্রযোজ্য: Avada শর্টকোড/এলিমেন্ট আপনার আউটপুটকে র্যাপ করতে পারে। একটি কার্যকরী পরীক্ষা হলো: যাচাই করুন যে আপনার শর্টকোডটি একটি স্থিতিশীল, এস্কেপড স্ট্রিং রিটার্ন করে।
- আপনি যদি একটি “ফিউশন এলিমেন্ট” প্রদান করেন, তাহলে অপশন (অ্যারে) তৈরি করার প্রক্রিয়াটি আলাদা করুন এবং ইউনিট মোডে এটি পরীক্ষা করুন।
চূড়ান্ত যাচাই
- প্লাগইনের ভিতরে: এক্সটেনশানগুলি → “BPCAB ডেমো (পরীক্ষাযোগ্য)” সক্রিয় করুন।
- একটি পৃষ্ঠা তৈরি করুন
[bpcab_hello name="Test"]আপনি “Hello Test!” দেখতে পাবেন। - কমান্ড লাইন ইন্টারফেসে, প্লাগইন ফোল্ডার থেকে:
composer test:unitসবুজ স্যুট, খুব দ্রুত সম্পাদন।composer test:integrationসবুজ স্যুট, ধীরগতির, ডিবি ব্যবহৃত।
- গিটহাবে: push → “Tests” ওয়ার্কফ্লোটি ম্যাট্রিক্সের PHP ভার্সনগুলোতে পরিবর্তিত হয়।
যদি ফলাফল প্রত্যাশিত না হয়
| লক্ষণ | সম্ভাব্য কারণ | প্রতিপাদন | সমাধান |
|---|---|---|---|
| PHPUnit: “ক্লাসটি খুঁজে পাওয়া যায়নি” | অটোলোড পিএসআর-৪ ভুলভাবে কনফিগার করা হয়েছে | চেহারা composer.json এবং ফাইল নেমস্পেস |
composer dump-autoload, ঠিক BpcabDemo\ → src/ |
| ইন্টিগ্রেশন: “ওয়ার্ডপ্রেস টেস্ট ফোল্ডার খুঁজে পাওয়া যায়নি” | WP_DEVELOP_DIR ত্রুটিপূর্ণ |
echo $WP_DEVELOP_DIR পথটি পরীক্ষা করুন |
সঠিক পথে এগিয়ে যান wordpress-develop |
| ইন্টিগ্রেশন: “ডাটাবেস সংযোগ স্থাপনে ত্রুটি” | টেস্ট ডেটাবেসটি বিদ্যমান নেই অথবা ক্রেডেনশিয়ালগুলি ভুল। | ক্রেডেনশিয়াল ব্যবহার করে MySQL-এ লগ ইন করুন | তৈরি wp_testsসঠিক হোস্ট/ইউজার/পাস |
| টেস্ট মোডে শর্টকোডটি সেভ হয় না। | প্লাগইন লোড হয়নি muplugins_loaded |
চেক tests/bootstrap-integration.php |
সংশোধন করুন require .../bpcab-demo.php (পথ) |
| ইউনিটে PHP ত্রুটি “add_action() ফাংশনের অনির্ধারিত কল” | একটি ইউনিট টেস্ট WP-এর উপর নির্ভরশীল কোড লোড করে। | স্ট্যাক ট্রেস দেখুন | যুক্তি পরিবর্তন করুন Domainইন্টিগ্রেশনে মকিং বা টেস্টিং |
সমস্যা সমাধানের সময় আমি প্রায়শই যে সমস্যাগুলো দেখি:
- কোডটি ভুল জায়গায় কপি করা হয়েছে (যেমন:
tests/bootstrap-integration.phpভিতরে রাখুনsrc/). - বুটস্ট্র্যাপ দ্বারা লোড করা একটি ফাইলে সেমিকোলন না থাকায়, PHPUnit কোনো টেস্ট দেখানোর আগেই থেমে যায়।
- অ্যাকশন/ফিল্টার বিভ্রান্তি: আপনি ব্যবহার করছেন
add_actionপরিবর্তেadd_filter(অথবা এর বিপরীত), এবং পরীক্ষাটি “কিছুই দেখতে পায় না”। - আপনি "শুধু দেখার জন্য" প্রোডাকশনে পরীক্ষা করছেন: টেস্ট ডাটাবেসটি অপশনগুলো ওভাররাইট করে দিচ্ছে। এমনটা করবেন না।
- আপনার প্লাগইনটি খুব তাড়াতাড়ি/খুব দেরিতে লোড হচ্ছে: হুকগুলো উপলব্ধ নেই, অথবা ডিপেন্ডেন্সিগুলো লোড হয়নি।
সাধারণ ফাঁদ এবং ভুলগুলি
| এরর | কারণ | সমাধান |
|---|---|---|
| অস্থিতিশীল (অস্থির) ইন্টিগ্রেশন পরীক্ষা | সামগ্রিক WP স্টেট পরিষ্কার করা হয়নি (অপশন, ট্রানজিয়েন্ট, হুক যোগ করা হয়েছে) | পরিষ্কার করুন tearDown()গ্লোবাল সিঙ্গেলটন পরিহার করুন, সাইড ইফেক্ট সীমিত করুন |
| হেডারগুলো ইতিমধ্যে পাঠানো হয়েছে। | বাফারিং শুরু হওয়ার আগেই একটি পরীক্ষা পুনঃনির্দেশনা/প্রস্থান ঘটায়। | চূড়ান্ত অবস্থা পরীক্ষা করুন, বাধা দিন wp_redirectহেডারের উপর অ্যাসার্ট করা এড়িয়ে চলুন |
| “হেডার তথ্য পরিবর্তন করা যাবে না” শুধুমাত্র CI-তে | পিএইচপি এক্সটেনশন / আউটপুট বাফারিং-এর পার্থক্য | PHPUnit-এ HTTP স্ট্রিমের উপর নির্ভর করবেন না; এর জন্য এন্ড-টু-এন্ড টেস্ট ব্যবহার করুন। |
| একটি পুরোনো টিউটোরিয়ালে সেকেলে স্ক্রিপ্ট ব্যবহারের পরামর্শ দেওয়া হয়েছে। | PHPUnit / WP টেস্ট স্যুটের বিবর্তন | বর্তমান মূল ডকুমেন্টেশন এবং এর সাথে সামঞ্জস্যপূর্ণ wordpress-develop (এপ্রিল 2026) |
| স্নিপেটস প্লাগইনটি টেস্টগুলো ভেঙে দেয়। | টেস্ট এনভায়রনমেন্টে রানটাইম কোড লোড করা হয়েছে | আপনার প্লাগইনটি একটি ন্যূনতম পরিবেশে পরীক্ষা করুন; অপ্রয়োজনীয় mu-plugins নিষ্ক্রিয় করুন। |
| পুরানো PHP সম্পর্কিত ত্রুটি | পিএইচপি ৭.x/৮.০-তে সিআই অথবা লোকাল মেশিন | PHP 8.1+ এ আপগ্রেড করুন (দেখুন সমর্থিত পিএইচপি সংস্করণ) |
রূপভেদ / বিকল্প
বিকল্প “ওয়ার্ডপ্রেস টেস্ট স্যুট ছাড়া” (শুধুমাত্র ইউনিটের জন্য)
আপনার প্লাগইনটি যদি প্রধানত বিশুদ্ধ লজিক-ভিত্তিক হয় (যেমন গণনা, পার্সিং, এপিআই পেলোড তৈরি), তবে আপনি নিম্নলিখিত বিষয়গুলির মধ্যে নিজেকে সীমাবদ্ধ রাখতে পারেন:
- কম্পোজার + পিএইচপিইউনিট,
- ইউনিট পরীক্ষা
src/Domain, - ইন্টিগ্রেশন টেস্টের পরিবর্তে অল্প সংখ্যক ম্যানুয়াল “স্মোক” টেস্ট করা হয়।
একটি সাধারণ অভ্যন্তরীণ প্লাগইনের জন্য এটি গ্রহণযোগ্য, কিন্তু এর ফলে আপনি WP হুক, রোল, ননস এবং বিহেভিয়ারের কভারেজ হারাবেন।
“আরও উন্নত” বিকল্প: ক্ষণস্থায়ী পরিবেশে ইন্টিগ্রেশন টেস্টিং
জটিল প্লাগইনগুলির ক্ষেত্রে, আমি প্রায়শই একটি ডিসপোজেবল পরিবেশে ইন্টিগ্রেশনটি চালাতে পছন্দ করি:
- ডকার কম্পোজ (মাইএসকিউএল + ওয়ার্ডপ্রেস + সিএলআই),
- আইভরি কোস্টে ওয়ার্ডপ্রেস ইনস্টলেশন,
- PHPUnit টেস্ট এবং e2e-এর জন্য সম্ভবত Playwright/Cypress।
এটি ওজনে ভারী, কিন্তু উৎপাদনের কাছাকাছি থাকা স্তূপগুলোর ক্ষেত্রে এটি অপ্রত্যাশিত পরিস্থিতি কমিয়ে দেয়।
নিরাপত্তা, কর্মক্ষমতা এবং রক্ষণাবেক্ষণের পরামর্শ
- নিরাপত্তা সর্বদা "প্রত্যাখ্যাত" পাথগুলো (অবৈধ ক্যাপাবিলিটি, ননস) পরীক্ষা করুন। নিরাপত্তা ত্রুটিগুলো প্রায়শই "আমি অ্যাডমিন হলে তো এটা কাজ করে" এই ধারণা থেকেই উদ্ভূত হয়।
- অন্তরণ টেস্ট ডেটাবেসটি অন্য কিছুর সাথে কখনো শেয়ার করবেন না। এমনকি স্থানীয়ভাবেও না।
- সম্পাদন ৮০% টেস্ট ইউনিট টেস্টিং-এর মধ্যে রাখুন। ইন্টিগ্রেশন টেস্টের কাজ হলো অ্যাসেম্বলিকে যাচাই করা, প্রতিটি কেস পুনরায় চালানো নয়।
- রক্ষণাবেক্ষণ যখন ওয়ার্ডপ্রেস ৬.৯.এক্স উন্নত হবে, আপনি চাইবেন যে আপনার ব্যবহারকারীদের জানানোর আগেই সিআই (CI) আপনাকে জানাক যে এতে কোনো সমস্যা হচ্ছে।
- কম্প্যাট যদি আপনি একাধিক WP সংস্করণ সমর্থন করেন, তাহলে একটি CI ম্যাট্রিক্স (যেমন: 6.7, 6.8, 6.9.4) তৈরি করুন এবং কিছু শর্তসাপেক্ষ সমন্বয় গ্রহণ করুন।
আরও যেতে
- পরীক্ষা যোগ করুন বিশ্রাম এপিআই (রুট, কলব্যাক অনুমতি, স্কিমা)।
- আপনার ডিবি মাইগ্রেশন পরীক্ষা করুন (টেবিল তৈরি,
dbDelta()একীকরণে। - সেট আপ a সার্ভিস প্রোভাইডার (ক্লিনার কন্টেইনার) এবং ওয়্যারিং পরীক্ষা করুন।
- একটি ধাপ যোগ করুন স্ট্যাটিক বিশ্লেষণ (পিএইচপি স্ট্যান/গীতসংহিতা) + কোডিং মান CI-তে (PHPCS WordPress)।
- আপনার যদি JS (ব্লক) থাকে, তাহলে Jest/Vitest যোগ করুন এর মাধ্যমে @wordpress/scripts এবং পাইপলাইনগুলো আলাদা করুন।
সম্পদ
- ওয়ার্ডপ্রেস কোর হ্যান্ডবুক – পিএইচপিইউনিট
- গিটহাব – ওয়ার্ডপ্রেস/ওয়ার্ডপ্রেস-ডেভেলপ
- WP_UnitTestCase (রেফারেন্স)
- প্লাগইন হ্যান্ডবুক – ননসেস
- add_shortcode() (রেফারেন্স)
- PHPUnit অফিসিয়াল ডকুমেন্টেশন
- ওয়ার্ডপ্রেস কোর ট্র্যাক (কোর সাইডে টেস্টিং/সিআই পরিবর্তন ট্র্যাক করার জন্য উপযোগী)
- পিএইচপি ম্যানুয়াল
FAQ
ওয়ার্ডপ্রেস লোড করে সবকিছু পরীক্ষা না করে “ইউনিট” এবং “ইন্টিগ্রেশন” আলাদা করা হচ্ছে কেন?
কারণ ওয়ার্ডপ্রেস লোড করলে টেস্টগুলো ধীর, অনির্ভরযোগ্য এবং সমস্যা নির্ণয় করা কঠিন হয়ে পড়ে। আমি অ্যাসেম্বলি (হুক, রোল, ডেটাবেস) ভ্যালিডেট করার জন্য ওয়ার্ডপ্রেস রাখি এবং বিজনেস লজিক বিশুদ্ধ পিএইচপি-তে টেস্ট করি।
PHPUnit 11 কি আবশ্যক?
না, তবে PHP 8.1+ এর ক্ষেত্রে এটি একটি সামঞ্জস্যপূর্ণ এবং রক্ষণাবেক্ষণ করা সংস্করণ। আপনার স্ট্যাকে সীমাবদ্ধতা থাকলে, সেই অনুযায়ী সংস্করণটি বেছে নিন। composer.jsonPHPUnit ডকুমেন্টেশনের সামঞ্জস্যতা বিভাগটি দেখুন।
একটি “সাধারণ” ওয়ার্ডপ্রেসের পরিবর্তে ওয়ার্ডপ্রেস-ডেভেলপ ক্লোন করা কেন প্রয়োজন?
কারণ WP টেস্ট স্যুটটি থাকে wordpress-develop/tests/phpunitআপনি অন্য উপায়ে এটি নিয়ে নাড়াচাড়া করতে পারেন, কিন্তু তাতে আপনি কোর দ্বারা ইতিমধ্যে রক্ষণাবেক্ষণ করা স্ক্রিপ্টগুলোকেই নতুন করে তৈরি করবেন।
আমার ইন্টিগ্রেশন টেস্টগুলো খুব ধীরগতির। আমার কী করা উচিত?
এগুলোর সংখ্যা কমান, ইন্টিগ্রেশন পয়েন্টগুলোতে এগুলোকে কেন্দ্রীভূত করুন, এবং বাকিগুলো ইউনিট টেস্টে সরিয়ে দিন। CI-তে, কম্পোজার ক্যাশে ব্যবহার করুন এবং অতিরিক্ত হিস্ট্রি ক্লোন করা এড়িয়ে চলুন (এজন্য) --depth=1).
যে হুকটি ক্রম/অগ্রাধিকারের উপর নির্ভর করে, সেটি আমি কীভাবে পরীক্ষা করব?
চূড়ান্ত ফলাফল (আউটপুট/অবস্থা) পরীক্ষা করুন, এবং এমন একটি টেস্ট যোগ করুন যা কলব্যাকটির উপস্থিতি যাচাই করে। has_action() / has_filter() প্রাসঙ্গিক হলে। দ্রষ্টব্য: এই ফাংশনগুলো নিবন্ধন যাচাই করে, কার্য সম্পাদন নয়।
যে কোডটি কাজ করে তা কীভাবে পরীক্ষা করবেন exit ?
সাধারণত, আপনি অবস্থা পরীক্ষা করেন (আপডেট অপশন, পোস্ট তৈরি হয়েছে কিনা) এবং যা পারেন তা ইন্টারসেপ্ট করেন (ফিল্টার)। wp_redirectপ্রস্থানের অধিকার আদায়ের জন্য লড়াই করবেন না।
আমি একটি ইউনিট টেস্টে “Call to undefined function esc_html()” এই ত্রুটিটি দেখতে পাচ্ছি। এটা কি স্বাভাবিক?
হ্যাঁ : esc_html() এটি একটি ওয়ার্ডপ্রেস ফাংশন। আপনি যদি ইউনিট টেস্ট করতে চান, তাহলে লজিকটিকে একটি পিওর পিএইচপি ক্লাসে আলাদা করুন এবং ইন্টিগ্রেশনে এস্কেপিং পরীক্ষা করুন, অথবা একটি এস্কেপিং স্ট্র্যাটেজি ইনজেক্ট করুন (যা আরও উন্নত পদ্ধতি)।
আমি কি PHPUnit দিয়ে Elementor/Divi/Avada পরীক্ষা করতে পারি?
আপনি আপনার ইন্টিগ্রেশন কোড পরীক্ষা করতে পারেন (যেমন, "আমার উইজেটটি সঠিক হুকে রেজিস্টার হচ্ছে"), কিন্তু সম্পূর্ণ UI নয়। UI-এর জন্য, একটি টেস্ট সাইটে এন্ড-টু-এন্ড টেস্ট (প্লেরাইট/সাইপ্রেস) ব্যবহার করুন।
আমার কি প্রতিশ্রুতিবদ্ধ হওয়া উচিত? vendor/ আমার প্লাগইনে?
কম্পোজারের বাইরে বিতরণ করা একটি প্লাগইনের জন্য, অনেক প্লাগইনে অন্তর্ভুক্ত থাকে vendor/কম্পোজার দ্বারা পরিচালিত অভ্যন্তরীণ প্লাগইনের ক্ষেত্রে, না। সব ক্ষেত্রেই, আপনাকে CI-তে ডিপেন্ডেন্সিগুলো ইনস্টল করতে হবে।
ওয়ার্ডপ্রেসে একাধিক সংস্করণের সামঞ্জস্যতা কীভাবে পরিচালনা করবেন?
একাধিক WP ভার্সন জুড়ে একটি CI ম্যাট্রিক্স যোগ করুন এবং আপনার ইউনিট টেস্টগুলোকে স্বাধীন রাখুন। কোর পরিবর্তনের জন্য, টিকেটগুলো অনুসরণ করুন। মঞ্চভীতি এবং জনসংযোগের উপর GitHub.
ওয়ার্ডপ্রেস ৬.৯.৪-এ কোনো পুরোনো টিউটোরিয়াল স্নিপেট কাজ না করলে কী করতে হবে?
জোর করে কিছু করবেন না। বর্তমান WP টেস্ট স্যুটের (wordpress-develop) সাথে নিজেকে মানিয়ে নিন এবং সেই অনুযায়ী আপনার বুটস্ট্র্যাপকে পরিবর্তন করুন। পুরনো ব্লগগুলিতে পাওয়া পুরোনো টেস্ট ইনস্টলেশন স্ক্রিপ্টগুলি প্রায়শই PHPUnit (পরিবর্তিত API) এবং স্যুট পাথের কারণে কাজ করা বন্ধ করে দেয়।