Testy
Projekt používá Pest PHP pro testování. Testy jsou organizovány do tří kategorií: Unit, Integration a Architecture. Všechny jsou uloženy v adresáři /tests.
Spuštění testů
Všechny testy
./pest
Konkrétní kategorii testů
./pest tests/Unit
./pest tests/Integration
./pest tests/Architecture
Filtrování podle názvu
./pest --filter CacheTest
./pest --filter "save item"
./pest --filter Cache tests/Unit
Konkrétní soubor
./pest tests/Unit/Core/Cache/CacheTest.php
Testy se skupinami
./pest --group architecture
./pest --group database
./pest --group cache
Paralelní běh (zrychlení)
./pest --parallel
Struktura testů
tests/
├── Unit/ # Jednotlivé komponenty bez závislostí
│ └── Core/
│ ├── Array/
│ │ └── ArrayTest.php
│ ├── Cache/
│ │ └── CacheTest.php
│ ├── FileSystem/
│ │ ├── DirTest.php
│ │ ├── FileTest.php
│ │ ├── FileInfoTest.php
│ │ ├── FilesTest.php
│ │ └── FileSystemTest.php
│ └── Ip/
│ └── IpTest.php
│
├── Integration/ # Interakce se skutečnou databází
│ └── Core/
│ ├── Cache/
│ │ └── CacheFileIntegrationTest.php
│ └── Database/
│ ├── DBTest.php
│ ├── DBSetTest.php
│ ├── DBSpecialCasesTest.php
│ └── DBPrepareExecuteTest.php
│
├── Architecture/ # Globální pravidla kódu
│ ├── DatabaseAndOverallArchTest.php
│ ├── MiddlewareAndRoutingArchTest.php
│ ├── DataLayerArchTest.php
│ ├── ControllersArchTest.php
│ ├── TemplateLayerArchTest.php
│ ├── CubeSystemArchTest.php
│ └── ArchitectureHelper.php
│
├── Utils/
│ └── DatabaseSetup.php
│
└── Pest.php # Globální Pest konfigurace
Psaní testů
Jednoduchý Unit test
<?php
declare(strict_types=1);
use Petrovo\Cache\Cache;
test('save item with valid data', function () {
$itemName = 'test_item';
$data = ['key' => 'value'];
Cache::set($itemName, $data, 60);
expect(Cache::get($itemName))->toEqual($data);
});
test('save item with empty array', function () {
Cache::set('test', [], 60);
expect(Cache::get('test'))->toEqual([]);
});
Test se skupinou a tagy
<?php
test('SQL is parameterized', function () {
// test code
})
->group('architecture', 'database');
Integration test s databází
<?php
declare(strict_types=1);
use Petrovo\Database\DB;
// Databáze se automaticky inicializuje (viz Pest.php)
// Transakce se vrací po testu (rollback)
test('insert user', function () {
DB::query("INSERT INTO users (name) VALUES (?)", ['Alice']);
expect(DB::$affectedRows)->toEqual(1);
expect(DB::$insertId)->toBeGreaterThan(0);
});
test('query user', function () {
$user = DB::row("SELECT * FROM users WHERE name = ?", ['Alice']);
expect($user->name)->toEqual('Alice');
});
Test s Before/After hooks
<?php
beforeAll(function () {
// Spustí se jednou na začátku všech testů v souboru
Cache::clear();
});
afterAll(function () {
// Spustí se jednou na konci všech testů v souboru
Cache::clear();
});
test('uses clean cache', function () {
// Cache je čistá
});
Expect Assertions (Pest)
Pest používá fluent syntaxi přes expect():
// Základní kontroly
expect($result)->toBe(true);
expect($result)->toBeTrue();
expect($result)->toBeFalse();
expect($result)->toBeNull();
// Porovnání
expect($value)->toEqual(5);
expect($value)->toBe(5); // Striktnější (===)
expect($value)->toNotEqual(5);
// Typy
expect($value)->toBeArray();
expect($value)->toBeString();
expect($value)->toBeInt();
expect($value)->toBeInstanceOf(stdClass::class);
// Stringy
expect($text)->toContain('substring');
expect($text)->toMatch('/pattern/');
expect($text)->toStartWith('prefix');
expect($text)->toEndWith('suffix');
// Kolekce
expect($array)->toHaveCount(3);
expect($array)->toHaveKey('key');
expect($array)->toContainEqual('value');
// Řetězování
expect($result)
->toBeArray()
->toHaveCount(3)
->toHaveKey('status')
->and($result['status'])->toEqual('ok');
Chyby a výjimky
// Kontrola vyhozené výjimky
expect(function () {
throw new Exception('Error message');
})->toThrow(Exception::class);
// S konkrétní zprávou
expect(function () {
throw new Exception('Custom error');
})->toThrow(Exception::class, 'Custom error');
// V PHPUnit stylu (legacy)
$this->expectException(Exception::class);
$this->expectExceptionMessage('message');
Fixture Data & Faker
Projektuje k dispozici knihovna Faker pro generování testovacích dat:
<?php
use Faker\Factory;
beforeEach(function () {
$faker = Factory::create('cs_CZ');
$this->user = [
'name' => $faker->name(),
'email' => $faker->email(),
'phone' => $faker->phoneNumber(),
'city' => $faker->city(),
];
});
test('creates user with faker data', function () {
expect($this->user['name'])->toBeString();
});
Pest Konfigurace
Konfigurace je v tests/Pest.php:
// Automatická inicializace databáze pro Integration/Database testy
uses()
->beforeEach(fn() => DatabaseSetup::init())
->in('Integration/Core/Database');
Běžné Příklady
Test Cache komponenty
./pest --filter CacheTest
./pest tests/Unit/Core/Cache/CacheTest.php
Jen Unit testy
./pest tests/Unit
Jen Architecture testy
./pest tests/Architecture
S detailním výstupem
./pest -vv tests/Unit/Core/Cache/CacheTest.php
Best Practices
- Jeden test = jednu věc: Každý
test()by měl testovat jednu funkcionalitu - Jasné názvy:
test('save item with valid data')je lepší nežtest('save') - Arrange-Act-Assert: Příprava → Spuštění → Kontrola
- Čisté testy: Database/Cache se automaticky čistí mezi testy
- Skupiny: Používej
->group('category')pro filtrování
Continuous Integration
Při commitu spustit testy:
./pest
Jen testy bez lintů:
./pest