Test yazmak
Modülünüzün testleri Tests/ klasöründe yaşar ve modülle birlikte gider:
cp-content/modules/Ornek/Tests/
Unit/ çekirdek ya da veritabanı gerektirmeyen saf mantık
Integration/ açılmış bir çekirdek ve gerçek veritabanı gerektirenler
Ad alanı Modules\Ornek\Tests\...'tır. Test çerçevesi PHPUnit 11'dir.
Birim testi
Saf sınıflar (dönüştürücü, hesaplayıcı, politika) için çekirdeği açmadan test yazın. Hızlıdır ve çoğu hatayı yakalar.
namespace Modules\Ornek\Tests\Unit;
use Modules\Ornek\Service\SlugCleaner;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
#[CoversClass(SlugCleaner::class)]
final class SlugCleanerTest extends TestCase
{
public function testStripsPathSegments(): void
{
self::assertSame('abc', (new SlugCleaner())->clean('../abc'));
}
}
Entegrasyon testi
Denetleyici, depo ya da servis bağlantıları test edecekseniz IntegrationTestCase kullanın. Bu taban sınıf:
- Test ortamında (
APP_ENV=test) bir çekirdek açar, - veritabanı şemasını şu anki eşlemeye göre sıfırlar (her test yöntemi temiz bir şema alır),
- çalışan konteynere erişim verir (
$this->container(),$this->em()).
namespace Modules\Ornek\Tests\Integration;
use App\Tests\Support\IntegrationTestCase;
use Modules\Ornek\Entity\Item;
use PHPUnit\Framework\Attributes\CoversClass;
#[CoversClass(Item::class)]
final class ItemPersistenceTest extends IntegrationTestCase
{
public function testItemIsStored(): void
{
$item = new Item();
$item->title = 'Deneme';
$this->em()->persist($item);
$this->em()->flush();
$this->em()->clear();
self::assertSame('Deneme', $this->em()->find(Item::class, $item->getId())?->title);
}
}
Entegrasyon testleri şemayı sıfırlar: tabloları siler ve yeniden kurar. Test ortamının DATABASE_URL'inin canlı ya da geliştirme verinizi değil, ayrı bir test veritabanını gösterdiğinden emin olun.
HTTP sözleşmesini sınamak
Bir yönetim denetleyicisi için asıl önemli şeyler HTTP sözleşmesidir: yetki, CSRF ve girdi doğrulama. Forum modülünün yükleme testi iyi bir örnektir: form yükleme ucunu açıkça gösteriyor mu, yetkili üye depolanmış bir varlık adresi alıyor mu, CSRF yoksa, dosya yoksa ya da dosya görsel değilse reddediliyor mu.
Bir isteği oturumla birlikte yığına itmek için taban sınıfın yardımcılarını kullanın ve denetleyiciyi doğrudan çağırın.
Neyi test etmeli?
| Alan | Örnek soru |
|---|---|
| Yetki | Yeteneği olmayan kullanıcı 403 alıyor mu? Menüde görünüyor mu? |
| CSRF | Belirteçsiz POST reddediliyor mu? |
| Girdi sınırı | Çok uzun ya da boş girdi, kötü niyetli içerik nasıl işleniyor? |
| Çıktı kaçışlama | <script> içeren başlık şablonda kaçışlanıyor mu? |
| Migration idempotent mi | SQL dosyası iki kez çalıştırılınca hata vermiyor mu? |
| Yükseltme | Eski şemadan yeni şemaya geçiş veriyi koruyor mu? |
| Anonim istek | Genel sayfa oturum çerezi bırakıyor mu? (önbellek ön koşulu) |
| Karantina | Hook'unuz hata verirse sayfa yine de çiziliyor mu? |
Çalıştırmak
composer test # tüm test paketi
cp-includes/vendor/bin/phpunit cp-content/modules/Ornek/Tests/Unit/SlugCleanerTest.php # tek dosya
Geliştirirken yalnızca yazdığınız ya da dokunduğunuz testi çalıştırın; tüm paket uzundur. Tüm paketi dağıtım öncesinde ya da CI'da çalıştırın.
Statik analiz
Projede PHPStan (phpstan-phpunit eklentisiyle) ve kod biçimi için composer lint komutu vardır. Yeni kodda declare(strict_types=1); kullanın ve türleri açık yazın.
Çekirdek davranışlarına bağımlı testler
Çekirdekten Core\Update\... ya da kurulum davranışına bağımlı test yazıyorsanız sürüm numaralarını sabit yazmayın: CpVersion::VERSION ile karşılaştırın; çekirdek her yayında artar.