Testing {#testing}#
Tina4 projects use PHPUnit for testing. Each module in the Tina4 ecosystem includes a phpunit.xml configuration and a tests/ directory.
Hot tips!
- Use SQLite (
:memory:) for database tests, no external services needed - Run
composer testfrom any Tina4 module to execute its test suite - All Tina4 modules target PHPUnit 9 with PHP 8.1+
Setting Up Tests {#setup}#
Install PHPUnit#
PHPUnit is included as a dev dependency in Tina4 modules:
bash
composer require --dev phpunit/phpunit ^9Create phpunit.xml#
xml
<?xml version="1.0" encoding="UTF-8"?><phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" verbose="true"> <testsuites> <testsuite name="default"> <directory>tests</directory> </testsuite> </testsuites></phpunit>Add a Test Script to composer.json#
json
{ "scripts": { "test": "./vendor/bin/phpunit tests --color" }}Writing Tests {#writing-tests}#
Basic Test#
php
<?phpโnamespace Tests;โuse PHPUnit\Framework\TestCase;โclass MyTest extends TestCase{ public function testExample(): void { $this->assertTrue(true); }}Testing with a Database#
Use SQLite in-memory for fast, isolated database tests:
php
<?phpโnamespace Tests;โuse PHPUnit\Framework\TestCase;use Tina4\DataSQLite3;โclass DatabaseTest extends TestCase{ private $DBA;โ protected function setUp(): void { $this->DBA = new DataSQLite3(":memory:"); $this->DBA->exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"); $this->DBA->exec("INSERT INTO users (name, email) VALUES ('John', 'john@example.com')"); }โ public function testFetchUsers(): void { $result = $this->DBA->fetch("SELECT * FROM users"); $this->assertEquals(1, $result->getNoOfRecords()); }โ public function testInsertUser(): void { $this->DBA->exec("INSERT INTO users (name, email) VALUES ('Jane', 'jane@example.com')"); $result = $this->DBA->fetch("SELECT * FROM users"); $this->assertEquals(2, $result->getNoOfRecords()); }}Testing ORM Objects#
php
<?phpโnamespace Tests;โuse PHPUnit\Framework\TestCase;use Tina4\DataSQLite3;โclass ORMTest extends TestCase{ protected $DBA;โ protected function setUp(): void { global $DBA; $DBA = new DataSQLite3(":memory:"); $this->DBA = $DBA;โ $this->DBA->exec("CREATE TABLE user ( id INTEGER PRIMARY KEY AUTOINCREMENT, first_name TEXT, last_name TEXT, email TEXT )"); }โ public function testSaveAndLoad(): void { $user = new \App\User(); $user->firstName = "John"; $user->lastName = "Doe"; $user->email = "john@example.com"; $user->save();โ $loaded = (new \App\User())->load("id = ?", [1]); $this->assertEquals("John", $loaded->firstName); $this->assertEquals("john@example.com", $loaded->email); }}Testing Routes#
php
<?phpโnamespace Tests;โuse PHPUnit\Framework\TestCase;โclass RouteTest extends TestCase{ public function testGetRoute(): void { // Register the route \Tina4\Get::add("/api/test", function(\Tina4\Response $response) { return $response(["status" => "ok"]); });โ // Simulate a request $result = \Tina4\Routing::callRoute("/api/test", "GET"); $this->assertStringContainsString("ok", $result); }}Running Tests {#running}#
bash
# Run all testscomposer testโ# Run a specific test file./vendor/bin/phpunit tests/MyTest.phpโ# Run with verbose output./vendor/bin/phpunit tests -vvv --colorโ# Run a specific test method./vendor/bin/phpunit --filter testExample tests/MyTest.phpโ# Generate JUnit XML report./vendor/bin/phpunit tests --log-junit=tests/junit.xmlTest Organization {#organization}#
A typical Tina4 project test structure:
project/ tests/ bootstrap.php # Optional: custom setup before tests DatabaseTest.php # Database layer tests ORMTest.php # ORM model tests RouteTest.php # API endpoint tests ServiceTest.php # Business logic tests phpunit.xml # PHPUnit configurationBootstrap File#
If you need custom setup (e.g., defining constants, connecting to a test database):
php
<?php// tests/bootstrap.phpโif (!isset($_SERVER['DOCUMENT_ROOT'])) { $_SERVER['DOCUMENT_ROOT'] = dirname(__DIR__);}โrequire_once dirname(__DIR__) . '/vendor/autoload.php';Update phpunit.xml to use it:
xml
<phpunit bootstrap="tests/bootstrap.php" ...>CI Integration {#ci}#
All Tina4 modules include GitHub Actions CI. A typical workflow:
yaml
name: Testsโon: push: branches: [main] pull_request: branches: [main]โjobs: test: runs-on: ubuntu-latest strategy: matrix: php-version: ['8.1', '8.2', '8.3', '8.4']โ steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} - run: composer install --no-progress - run: composer test