Testing Overview

Auto Commerce uses a comprehensive testing strategy covering backend, frontend, and end-to-end testing.

Testing Layers

Layer Framework Purpose
Backend Pest PHP API, services, models
Frontend Jest/Vitest React components, hooks
E2E Playwright Full user workflows

Quick Links


Backend Testing

Auto Commerce uses Pest PHP for backend testing, providing an elegant and expressive testing experience. The testing framework covers unit tests, feature tests, and module-specific tests.

Testing Stack

  • Pest PHP - Modern PHP testing framework
  • PHPUnit - Underlying test runner
  • Laravel Testing Utilities - HTTP testing, database assertions
  • Database Transactions - Automatic rollback after each test

Running Tests

All Tests

# Run all tests
cd backend
./vendor/bin/pest

# With coverage
./vendor/bin/pest --coverage

Specific Test Files

# Run a specific test file
./vendor/bin/pest tests/Feature/Auth/LoginTest.php

# Run tests matching a pattern
./vendor/bin/pest --filter="can login"

Test Suites

# Run unit tests only
./vendor/bin/pest tests/Unit

# Run feature tests only
./vendor/bin/pest tests/Feature

Test Categories

Unit Tests (tests/Unit/)

Test individual classes and methods in isolation:

  • Models - Eloquent model tests (scopes, accessors, relationships)
  • Services - Business logic service tests
  • Providers - Service provider tests

Feature Tests (tests/Feature/)

Test complete features through HTTP requests:

  • Auth - Authentication flows (login, logout, registration)
  • API - API endpoint tests
  • Modules - Module system tests

Module Tests (modules/*/backend/tests/)

Each module can have its own test suite:

  • Feature - Module API endpoint tests
  • Unit - Module-specific unit tests

Test Directory Structure

backend/
├── tests/
│   ├── Feature/
│   │   ├── Auth/
│   │   │   ├── LoginTest.php
│   │   │   ├── LogoutTest.php
│   │   │   └── RegistrationTest.php
│   │   ├── Modules/
│   │   │   └── ModuleApiTest.php
│   │   └── Security/
│   │       └── TwoFactorAuthTest.php
│   ├── Unit/
│   │   ├── Models/
│   │   │   ├── ModuleTest.php
│   │   │   └── ModuleInstallationTest.php
│   │   ├── Services/
│   │   │   └── ModuleManagerTest.php
│   │   └── Providers/
│   │       └── ModulesServiceProviderTest.php
│   ├── Pest.php           # Global test configuration
│   ├── TestCase.php       # Base test case
│   └── ModuleTestCase.php # Module testing base class

Writing Tests

Basic Test Structure

<?php

use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;

uses(Tests\TestCase::class, DatabaseTransactions::class);

describe('User Registration', function () {
    it('can register a new user', function () {
        $response = $this->postJson('/api/v1/auth/register', [
            'name' => 'Test User',
            'email' => 'test@example.com',
            'password' => 'password123',
            'password_confirmation' => 'password123',
        ]);

        $response->assertStatus(201);
        expect(User::where('email', 'test@example.com')->exists())->toBeTrue();
    });
});

Testing with Authentication

use App\Models\User;
use Laravel\Passport\Passport;

it('can access protected route when authenticated', function () {
    $user = User::factory()->create();
    Passport::actingAs($user);

    $response = $this->getJson('/api/v1/profile');

    $response->assertStatus(200);
});

Testing with Tenant Context

use App\Models\Tenant;

it('can access tenant-specific data', function () {
    $tenant = Tenant::create(['id' => 'test-tenant', 'name' => 'Test Tenant']);

    // Initialize tenant context
    tenancy()->initialize($tenant);

    // Run your test...

    // End tenant context
    tenancy()->end();

    // Cleanup
    $tenant->delete();
});

Configuration

phpunit.xml

The phpunit.xml file configures test suites:

<testsuites>
    <testsuite name="Unit">
        <directory>tests/Unit</directory>
    </testsuite>
    <testsuite name="Feature">
        <directory>tests/Feature</directory>
    </testsuite>
    <testsuite name="Modules">
        <directory>../modules/*/backend/tests</directory>
    </testsuite>
</testsuites>

Pest.php

Global test configuration in tests/Pest.php:

<?php

uses(Tests\TestCase::class, DatabaseTransactions::class)->in('Feature', 'Unit');

// Custom expectations
expect()->extend('toBeActiveModule', function () {
    return $this->toBeInstanceOf(Module::class)
        ->and($this->value->is_active)->toBeTrue();
});

Best Practices

  1. Use DatabaseTransactions - Automatically rollback database changes after each test
  2. Test in isolation - Each test should be independent and not rely on other tests
  3. Use factories - Leverage Laravel factories for creating test data
  4. Test edge cases - Include tests for error conditions and boundary cases
  5. Keep tests focused - Each test should verify one specific behavior
  6. Use meaningful names - Test names should describe what is being tested

Related Documentation