Testování
Testování
Section titled “Testování”Projekt používá Pest PHP jako testovací framework s podporou pro unit, feature a integrační testy.
Typy testů
Section titled “Typy testů”Unit testy
Section titled “Unit testy”- Testují izolované komponenty (třídy, metody)
- Umístění:
tests/Unit/ - Používají SQLite in-memory databázi pro rychlost
Feature testy
Section titled “Feature testy”- Testují kompletní funkcionality (HTTP requesty, workflow)
- Umístění:
tests/Feature/ - Používají MySQL testovací databázi
kviz_testing
Integrační testy
Section titled “Integrační testy”- Testují interakci mezi komponentami
- Umístění:
tests/Integration/ - Používají MySQL testovací databázi
Spouštění testů
Section titled “Spouštění testů”Všechny testy
Section titled “Všechny testy”docker compose exec -T fpm php vendor/bin/pestKonkrétní test soubor
Section titled “Konkrétní test soubor”docker compose exec -T fpm php vendor/bin/pest tests/Unit/CheckDatabaseTest.phpKonkrétní test
Section titled “Konkrétní test”docker compose exec -T fpm php vendor/bin/pest --filter="has correct database configuration"S coverage
Section titled “S coverage”docker compose exec -T fpm php vendor/bin/pest --coveragePouze určitá skupina
Section titled “Pouze určitá skupina”# Feature testydocker compose exec -T fpm php vendor/bin/pest tests/Feature/
# Unit testydocker compose exec -T fpm php vendor/bin/pest tests/Unit/Testovací databáze
Section titled “Testovací databáze”Testy používají dvě různé databázové konfigurace:
Unit testy - SQLite in-memory
Section titled “Unit testy - SQLite in-memory”Konfigurace v phpunit.xml:
<env name="DB_CONNECTION" value="sqlite"/><env name="DB_DATABASE" value=":memory:"/>Výhody:
- ⚡ Velmi rychlé
- 🔄 Čistý stav při každém testu
- 📦 Žádný setup
Feature testy - MySQL
Section titled “Feature testy - MySQL”Konfigurace v phpunit.xml:
<env name="DB_CONNECTION" value="mysql"/><env name="DB_HOST" value="db"/><env name="DB_PORT" value="3306"/><env name="DB_DATABASE" value="kviz_testing"/><env name="DB_USERNAME" value="kviz"/><env name="DB_PASSWORD" value="kviz"/>Vytvoření testovací databáze:
# V Docker kontejneru dbdocker compose exec db mysql -u kviz -pkviz -e "CREATE DATABASE IF NOT EXISTS kviz_testing;"
# Import schemadocker compose exec db mysql -u kviz -pkviz kviz_testing < database/schema/mysql-schema.sqlPsaní testů
Section titled “Psaní testů”Základní struktura (Pest)
Section titled “Základní struktura (Pest)”<?php
use App\Models\User;
test('user can be created', function () { $user = User::factory()->create([ 'email' => 'test@example.com', ]);
expect($user->email)->toBe('test@example.com');});
it('has correct name', function () { $user = User::factory()->create(['name' => 'John Doe']);
expect($user->name)->toBe('John Doe');});S použitím factory
Section titled “S použitím factory”use App\Modules\Region;
test('region factory creates valid data', function () { $region = Region::factory()->create();
expect($region) ->toBeInstanceOf(Region::class) ->and($region->country_id)->toBe(1) ->and($region->hidden)->toBeFalse();});Feature test s HTTP requestem
Section titled “Feature test s HTTP requestem”use App\User;
test('user can login', function () { $user = User::factory()->create([ 'password' => bcrypt('password123'), ]);
$response = $this->post('/login', [ 'email' => $user->email, 'password' => 'password123', ]);
$response->assertRedirect('/dashboard'); $this->assertAuthenticatedAs($user);});Použití seederů v testech
Section titled “Použití seederů v testech”use Database\Seeders\CountrySeeder;use Database\Seeders\RegionSeeder;
test('regions have countries', function () { $this->seed(CountrySeeder::class); $this->seed(RegionSeeder::class);
expect(\App\Modules\Country::count())->toBe(2) ->and(\App\Modules\Region::count())->toBe(14);});Testování s databázovými transakcemi
Section titled “Testování s databázovými transakcemi”use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('creates user in transaction', function () { $user = User::factory()->create();
expect(User::count())->toBe(1); // Po testu se databáze automaticky rollbackne});Best Practices
Section titled “Best Practices”1. Používejte Factories
Section titled “1. Používejte Factories”❌ Špatně:
$user = new User();$user->name = 'John';$user->email = 'john@example.com';$user->save();✅ Správně:
$user = User::factory()->create([ 'name' => 'John', 'email' => 'john@example.com',]);2. Descriptive test names
Section titled “2. Descriptive test names”❌ Špatně:
test('test1', function () { ... });✅ Správně:
test('user with admin role can access admin panel', function () { ... });3. Arrange-Act-Assert pattern
Section titled “3. Arrange-Act-Assert pattern”test('user can update profile', function () { // Arrange $user = User::factory()->create();
// Act $response = $this->actingAs($user)->put('/profile', [ 'name' => 'New Name', ]);
// Assert expect($user->fresh()->name)->toBe('New Name'); $response->assertSuccessful();});4. Izolujte testy
Section titled “4. Izolujte testy”Každý test by měl být nezávislý:
// ✅ Každý test má vlastní datatest('creates user', function () { $user = User::factory()->create(); expect(User::count())->toBe(1);});
test('creates another user', function () { $user = User::factory()->create(); expect(User::count())->toBe(1); // Ne 2!});5. Testujte edge cases
Section titled “5. Testujte edge cases”test('handles empty input', function () { $result = calculateTotal([]); expect($result)->toBe(0);});
test('handles null values', function () { $result = calculateTotal(null); expect($result)->toBe(0);});Debugging testů
Section titled “Debugging testů”Výpis dat během testu
Section titled “Výpis dat během testu”test('debug test', function () { $user = User::factory()->create();
dump($user->toArray()); // Vypíše data ray($user); // Pokud používáte Ray
expect($user)->toBeInstanceOf(User::class);});Zastavení na konkrétním místě
Section titled “Zastavení na konkrétním místě”test('stop here', function () { $user = User::factory()->create();
dd($user); // Die and dump - zastaví test
// Tento kód se neprovede expect($user)->toBe('something');});Spuštění s verbose výstupem
Section titled “Spuštění s verbose výstupem”docker compose exec -T fpm php vendor/bin/pest -vCoverage
Section titled “Coverage”Spuštění s coverage reportem
Section titled “Spuštění s coverage reportem”docker compose exec -T fpm php vendor/bin/pest --coverage --min=80HTML coverage report
Section titled “HTML coverage report”docker compose exec -T fpm php vendor/bin/pest --coverage-html coverage/Report se vytvoří v coverage/index.html.
Continuous Integration
Section titled “Continuous Integration”Testy by měly běžet v CI/CD pipeline před každým merge.
GitLab CI příklad
Section titled “GitLab CI příklad”test: stage: test script: - docker compose up -d db - docker compose exec -T fpm composer install - docker compose exec -T fpm php vendor/bin/pest only: - merge_requests - dev - masterČasté problémy
Section titled “Časté problémy”Testy selhávají kvůli chybějící databázi
Section titled “Testy selhávají kvůli chybějící databázi”# Vytvořte testovací databázidocker compose exec db mysql -u kviz -pkviz -e "CREATE DATABASE IF NOT EXISTS kviz_testing;"Testy jsou pomalé
Section titled “Testy jsou pomalé”- Používejte SQLite pro unit testy
- Používejte
RefreshDatabasemístomigrate:freshv každém testu - Optimalizujte factories (méně DB dotazů)
“Class not found” chyby
Section titled ““Class not found” chyby”# Regenerujte autoloaddocker compose exec fpm composer dump-autoloadTesty neprocházejí v CI, ale lokálně ano
Section titled “Testy neprocházejí v CI, ale lokálně ano”- Zkontrolujte environment proměnné v
phpunit.xml - Ověřte, že CI má přístup k databázi
- Zkontrolujte PHP verzi v CI vs lokálně