Skip to content

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

  1. Jeden test = jednu věc: Každý test() by měl testovat jednu funkcionalitu
  2. Jasné názvy: test('save item with valid data') je lepší než test('save')
  3. Arrange-Act-Assert: Příprava → Spuštění → Kontrola
  4. Čisté testy: Database/Cache se automaticky čistí mezi testy
  5. Skupiny: Používej ->group('category') pro filtrování

Continuous Integration

Při commitu spustit testy:

./pest

Jen testy bez lintů:

./pest