Ugrás a tartalomra
WordPress bővítmény- és téma-tesztelés PHPUnit-tel: gyakorlati útmutató WP-CLI scaffolddal
Patai László
Patai László 2026. január 27. · 15 perc olvasás

WordPress bővítmény- és téma-tesztelés PHPUnit-tel: gyakorlati útmutató WP-CLI scaffolddal

A WordPress-fejlesztés egyik legjobb befektetése az automatizált tesztelés. Nem azért, mert minden bug eltűnik tőle, hanem mert sokkal korábban veszed észre a hibákat, és nem a felhasználóid fognak szembesülni velük élesben. A WordPress ökoszisztémában a biztonsági problémák jelentős része bővítményekhez köthető; egy stabil tesztkészlet rengeteget segít abban, hogy kisebb eséllyel csússzon be regresszió vagy váratlan mellékhatás.

Miért érdemes komolyan venni a tesztelést?

Az automatizált tesztek (különösen a PHPUnit-alapú tesztek) több szinten is megtérülnek:

  • Hibák korai felismerése: nem a release napján derül ki, hogy egy edge case szétveri a kódot.
  • Regressziók megelőzése: ha egyszer már kijavítottál egy bugot, legyen róla teszt, hogy ne jöjjön vissza.
  • Jobb kódminőség: a tesztelhető kód jellemzően tisztább, jobban tagolt.
  • Magabiztosabb refaktorálás: ha a tesztkészlet zöld, sokkal kevésbé félsz belenyúlni a kódba.

Előfeltételek: mire lesz szükséged?

A WordPress PHPUnit tesztkörnyezethez pár alap összetevő kell. Ezeket érdemes előre összerakni, mert a scaffold parancsok ugyan generálnak fájlokat, de a futtatáshoz a környezetednek is készen kell állnia.

  • PHP 8.0+ (a PHPUnit 10 megköveteli)
  • Composer (függőségkezeléshez)
  • WP-CLI (WordPress parancssori eszköz)
  • MySQL/MariaDB (külön teszt adatbázishoz)
  • Subversion (svn) (a WordPress teszt fájlok letöltéséhez)

WP-CLI telepítése (gyors módszer)

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp

PHPUnit felvétele Composer-rel (ajánlott)

A PHPUnit-et érdemes projekt-szinten, dev függőségként felvenni. WordPress projektekben gyakori a kompatibilitási réteg használata is, erre való a yoast/phpunit-polyfills csomag (különböző PHPUnit/PHP verziók közti eltérések áthidalására).

{
  "require-dev": {
    "phpunit/phpunit": "^10.0",
    "yoast/phpunit-polyfills": "^2.0"
  }
}

Bővítmény tesztek generálása WP-CLI scaffolddal

A WP-CLI scaffold parancsai pont arra jók, hogy ne kézzel kelljen összeraknod a WordPress tesztkörnyezet tipikus fájljait. Bővítményhez a kiindulópont a wp scaffold plugin-tests.

wp scaffold plugin-tests my-plugin

Milyen fájlokat kapsz a generálás után?

A parancs létrehozza a PHPUnit futtatásához és a WordPress tesztkörnyezet bootstrappeléséhez szükséges alapokat. Tipikusan ezek jelennek meg a projektedben:

  • phpunit.xml.dist – a PHPUnit konfigurációja (suite-ok, bootstrap, beállítások).
  • bin/install-wp-tests.sh – telepítő script a WordPress tesztkörnyezethez.
  • tests/bootstrap.php – a tesztek inicializálása, WordPress betöltése a teszt futásához.
  • tests/test-sample.php – egy minta teszt, amivel gyorsan ellenőrizheted, hogy működik-e a setup.
  • .phpcs.xml.dist – PHP CodeSniffer szabályok (kódszabvány ellenőrzéshez).
  • .circleci/config.yml – CI konfiguráció (alapértelmezésben CircleCI-hez).

CI provider kiválasztása a scaffoldnál

Ha nem CircleCI-t használsz, a scaffold képes más CI szolgáltatókhoz is konfigurációt generálni. A --ci kapcsolóval tudod megadni, milyen pipeline formátumot szeretnél.

# GitHub Actions
wp scaffold plugin-tests my-plugin --ci=github

# GitLab CI
wp scaffold plugin-tests my-plugin --ci=gitlab

# CircleCI (alapértelmezett)
wp scaffold plugin-tests my-plugin --ci=circle

# Bitbucket Pipelines
wp scaffold plugin-tests my-plugin --ci=bitbucket

Tesztkörnyezet felhúzása az install-wp-tests.sh script segítségével

A scaffold által generált bin/install-wp-tests.sh a kulcs: ez rakja össze a WordPress-hez szükséges teszt infrastruktúrát. A szokásos munkafolyamat az, hogy belépsz a bővítmény könyvtárába, majd lefuttatod a scriptet a megfelelő paraméterekkel.

cd wp-content/plugins/my-plugin
bash bin/install-wp-tests.sh wordpress_test root password localhost latest

Mit jelentenek a paraméterek?

  • wordpress_test – a teszt adatbázis neve (minden adat törlődni fog ebben az adatbázisban).
  • root – MySQL felhasználó.
  • password – a MySQL felhasználó jelszava.
  • localhost – az adatbázis szerver címe.
  • latest – a WordPress verziója (adhatsz konkrétat is, például: 6.9).

Mit csinál a script a háttérben?

A script lényegében három nagy lépést automatizál:

  1. Létrehozza (vagy újrahúzza) a teszt adatbázist.
  2. Letölti a WordPress-t a /tmp mappába.
  3. Telepíti a WordPress teszt eszközöket (a PHPUnit-alapú WordPress teszt suite-hoz szükséges fájlokat).

Téma (theme) tesztek scaffoldolása

Témáknál ugyanez a logika, csak a scaffold parancs neve más: wp scaffold theme-tests. A CI konfigurációt itt is kérheted például GitHub Actions-hoz.

wp scaffold theme-tests my-theme --ci=github

A különbség a bootstrappelésnél lesz fontos: a tests/bootstrap.php témánál jellemzően gondoskodik arról, hogy a téma aktív legyen a tesztek futása közben.

Tesztek futtatása: a leggyakoribb parancsok

Ha egyszer megvan a környezet (adatbázis + WP teszt suite + függőségek), a futtatás egyszerű: a projekt könyvtárából elindítod a PHPUnit-et.

cd wp-content/plugins/my-plugin
phpunit

Ha minden rendben, valami ilyesmit látsz:

OK (1 test, 1 assertion)

Konkrét tesztek célzott futtatása

Nagyobb projekteknél sok időt spórolsz, ha nem mindig a teljes suite fut. A PHPUnit erre több opciót is ad:

# Egy teszt osztály
phpunit --filter TestClassName

# Egy teszt metódus
phpunit --filter test_method_name

# Csoport alapján
phpunit --group slow

Tesztek írása WordPress-hez: stabil alapok

Egy alap teszt osztály felépítése

WordPress-ben a klasszikus PHPUnit tesztek gyakran WP_UnitTestCase-ből származnak. A set_up() és tear_down() metódusokkal tudod rendbe tenni a környezetet tesztenként.

<?php

class Test_My_Plugin extends WP_UnitTestCase {

    public function set_up() {
        parent::set_up();
        // Teszt előkészítés
    }

    public function tear_down() {
        // Takarítás
        parent::tear_down();
    }

    public function test_plugin_is_active() {
        $this->assertTrue( is_plugin_active( 'my-plugin/my-plugin.php' ) );
    }
}

AAA minta: Arrange, Act, Assert

A jól olvasható tesztek egyik bevált receptje az AAA (Arrange, Act, Assert): előkészítesz mindent, végrehajtod a műveletet, majd ellenőrzöd az eredményt. Ettől a teszt nem csak működik, de később is gyorsan érthető marad.

public function test_coupon_applied_to_order() {
    // Arrange - előkészítés
    $order = $this->factory->order->create();
    $coupon = $this->create_coupon( 'SAVE10', 10 );

    // Act - végrehajtás
    $result = apply_coupon_to_order( $order, $coupon );

    // Assert - ellenőrzés
    $this->assertTrue( $result );
    $this->assertEquals( 10, get_order_discount( $order ) );
}

Beszédes tesztnevek: konvenció, ami tényleg segít

A tesztnevek legyenek önleírók. Ha egy CI futás elhasal, a teszt neve lesz az első, amit megnézel – és sokszor már abból tudni akarod, mi romlott el.

// Jó
public function test_user_can_subscribe_to_newsletter() {}
public function test_invalid_email_returns_error() {}
public function test_duplicate_subscription_is_prevented() {}

// Rossz
public function test_1() {}
public function test_subscription() {}

WordPress Test Factory: gyors adatkészítés tesztekhez

A WordPress teszt keretrendszer egyik legerősebb része a beépített factory rendszer: nagyon gyorsan tudsz felhasználót, bejegyzést, taxonómiát stb. generálni tesztadatnak. Így nem kézzel kell SQL-t vagy hosszú setupot írnod.

// Post létrehozása
$post_id = $this->factory->post->create([
    'post_title' => 'Test Post',
    'post_status' => 'publish'
]);

// User létrehozása
$user_id = $this->factory->user->create([
    'role' => 'administrator'
]);

// Több elem létrehozása
$post_ids = $this->factory->post->create_many( 5 );

// Term létrehozása
$term_id = $this->factory->term->create([
    'taxonomy' => 'category',
    'name' => 'Test Category'
]);

Külső HTTP hívások tesztelése: mockolás a pre_http_request filterrel

Ha a kódod külső API-t hív, tesztben nem szerencsés valós hálózati kérést futtatni: lassú, törékeny, és függ a külső szolgáltatótól. WordPress-ben erre kézenfekvő a pre_http_request filter (hook), amivel a HTTP réteg elé tudsz vágni és visszaadhatsz egy „mintha” választ.

public function test_api_call_returns_expected_data() {
    // Mock beállítása
    add_filter( 'pre_http_request', function( $preempt, $args, $url ) {
        if ( strpos( $url, 'api.example.com' ) !== false ) {
            return [
                'response' => [ 'code' => 200 ],
                'body' => json_encode( [ 'status' => 'success' ] )
            ];
        }
        return $preempt;
    }, 10, 3 );

    // Teszt végrehajtása
    $result = my_plugin_fetch_data();

    $this->assertEquals( 'success', $result['status'] );
}

Best practice-ek, amik hosszú távon megmentenek

1) Ne implementációt tesztelj, hanem viselkedést

Gyakori csapda, hogy egy belső megvalósítási részletre írsz tesztet (például transients, belső cache kulcsok, konkrét tárolási stratégia). Ezek refaktoráláskor változhatnak úgy, hogy közben a funkció viselkedése helyes marad – te mégis elhasaló teszteket kapsz.

// Rossz - transient implementációs részlet
public function test_data_is_cached() {
    fetch_data();
    $this->assertNotFalse( get_transient( 'my_cache_key' ) );
}

// Jó - viselkedés tesztelése
public function test_second_call_uses_cache() {
    $start = microtime( true );
    fetch_data();
    fetch_data(); // Második hívás gyorsabb kell legyen
    $duration = microtime( true ) - $start;

    $this->assertLessThan( 0.1, $duration );
}

2) Tartsd izoláltan a teszteket

A WordPress Test Library alapból segít abban, hogy minden teszt után visszaálljon az adatbázis állapota. Ezt könnyű elrontani, ha tesztek között megosztott állapotra építesz (például statikus property-ben tárolt ID-kra). Az ilyen tesztek sorrendfüggők lesznek, és CI-ben jönnek elő a legidegesítőbb, nehezen reprodukálható hibák.

// Rossz
private static $shared_post_id;

public function test_one() {
    self::$shared_post_id = $this->factory->post->create();
}

public function test_two() {
    // Ez a teszt függ test_one-tól
    $post = get_post( self::$shared_post_id );
}

// Jó
public function test_one() {
    $post_id = $this->factory->post->create();
    // Minden teszt önálló
}

3) Data provider-ek: több eset, kevesebb duplikáció

Ha ugyanazt a logikát több input-output kombinációval akarod lefedni (klasszikus példa: validáció), akkor a PHPUnit data provider-ei sokkal tisztábbá teszik a kódot.

/**
 * @dataProvider email_validation_provider
 */
public function test_email_validation( $email, $expected ) {
    $this->assertEquals( $expected, is_valid_email( $email ) );
}

public function email_validation_provider() {
    return [
        'valid email' => [ 'test@example.com', true ],
        'missing @' => [ 'testexample.com', false ],
        'missing domain' => [ 'test@', false ],
        'empty string' => [ '', false ],
    ];
}

4) Teszt csoportok: gyors és lassú futások szétválasztása

Nem minden teszt egyforma: lesznek villámgyors unit tesztek és lassabb integrációs tesztek. A PHPUnit group annotációival ezt jól tudod kezelni.

/**
 * @group slow
 * @group integration
 */
public function test_slow_operation() {
    // Lassú teszt
}

/**
 * @group fast
 * @group unit
 */
public function test_fast_calculation() {
    // Gyors teszt
}

Futtatási példák:

# Csak gyors tesztek
phpunit --group fast

# Lassú tesztek kihagyása
phpunit --exclude-group slow

Minta GitHub Actions workflow PHPUnit-hez (MySQL service-szel)

Ha GitHub Actions-t használsz, érdemes a teszteket több PHP- és WordPress-verzióval is lefuttatni. Az alábbi példa MySQL 8.0 service-t indít, majd matrixban végigpróbálja a megadott verziókat.

name: PHPUnit Tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: wordpress_test
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

    strategy:
      matrix:
        php-version: ['8.1', '8.2', '8.3']
        wordpress-version: ['6.8', '6.9', 'latest']

    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php-version }}
          extensions: mysqli, intl, zip, gd
          coverage: xdebug

      - name: Install Composer dependencies
        run: composer install --no-progress --prefer-dist

      - name: Install WordPress test suite
        run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 ${{ matrix.wordpress-version }}

      - name: Run PHPUnit
        run: vendor/bin/phpunit --coverage-text

Összefoglalás: a teljes folyamat röviden

Ha WordPress bővítményt vagy témát fejlesztesz, a WP-CLI scaffold parancsokkal meglepően gyorsan eljutsz egy működő PHPUnit setupig:

  1. Scaffoldold a teszteket: wp scaffold plugin-tests vagy wp scaffold theme-tests.
  2. Húzd fel a tesztkörnyezetet: bash bin/install-wp-tests.sh ... (külön teszt adatbázissal!).
  3. Futtasd a teszteket: phpunit (vagy CI-ben vendor/bin/phpunit).

A stabil tesztkészlet ismérvei: izolált tesztek, beszédes elnevezések, AAA szerkezet, és a viselkedés tesztelése implementációs részletek helyett. Ha ezt a néhány alapelvet követed, a tesztjeid nem akadályozni fognak, hanem gyorsítani a fejlesztést.

Patai László

Patai László

1999 óta foglalkozom nyílt forrású rendszerekkel, 2006 óta kimondottan WordPress-el. Szakterületem a nagy forgalmú weboldalak fejlesztése és üzemeltetése.

Összes bejegyzés

Csatlakozz a HelloWP közösséghez!

Beszélgess velünk a WordPressről, a webfejlesztésről, és oszd meg a tapasztalataidat más fejlesztőkkel.

- tag
- online
Csatlakozás

Sütiket használunk az élményed javítása érdekében. A folytatással elfogadod a Sütikre vonatkozó irányelveinket.