Testing Guide
Testing Guide
This guide covers how to test Cbox Base Images locally during development.
Test Infrastructure Overview
Cbox uses a layered testing approach:
| Test Type | Location | Purpose |
|---|---|---|
| Unit Tests | tests/unit/ |
Extension verification, configuration |
| E2E Tests | tests/e2e/ |
Framework integration, full scenarios |
| Matrix Tests | tests/unit/run-matrix-tests.sh |
Cross-variant testing |
Quick Start
Run All Unit Tests
cd tests/unit
./run-matrix-tests.sh --build
Run E2E Tests
cd tests/e2e
./run-e2e-tests.sh ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.3-bookworm
Run Specific Scenario
./run-e2e-tests.sh ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.3-bookworm laravel
E2E Test Scenarios
Available test scenarios in tests/e2e/scenarios/:
| Scenario | Tests |
|---|---|
plain-php |
Basic PHP functionality, extensions |
laravel |
Laravel detection, scheduler, permissions |
symfony |
Symfony detection, console, cache |
wordpress |
WordPress detection, wp-config handling |
health-checks |
Health check endpoints |
database |
MySQL, PostgreSQL, Redis connectivity |
security |
Security headers, file permissions |
image-formats |
GD, ImageMagick, libvips support |
cbox-init |
Process manager integration |
pest |
Pest/PHPUnit test execution |
browsershot |
Puppeteer/Browsershot capabilities |
dusk-capabilities |
Laravel Dusk browser testing |
Running Individual Scenarios
# Laravel E2E test
./tests/e2e/scenarios/test-laravel.sh
# Symfony E2E test
./tests/e2e/scenarios/test-symfony.sh
# Cbox Init integration
./tests/e2e/scenarios/test-cbox-init.sh
Test Fixtures
Test fixtures are located in tests/e2e/fixtures/:
fixtures/
├── laravel/ # Minimal Laravel app
│ ├── app/
│ │ ├── artisan
│ │ └── public/index.php
│ └── docker-compose.yml
├── symfony/ # Minimal Symfony app
│ ├── app/
│ │ ├── bin/console
│ │ ├── public/index.php
│ │ └── var/
│ └── docker-compose.yml
├── wordpress/ # Minimal WordPress setup
├── database/ # Database connectivity tests
├── security/ # Security validation tests
└── cbox-init/ # Process manager tests
Each fixture contains a docker-compose.yml that uses the IMAGE environment variable:
services:
app:
image: ${IMAGE:-ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.3-bookworm}
# ...
Matrix Testing
Test across all PHP versions and OS variants:
# Test all variants
./tests/unit/run-matrix-tests.sh --build
# Test only php-fpm images
./tests/unit/run-matrix-tests.sh --fpm --build
# Test only php-fpm-nginx images
./tests/unit/run-matrix-tests.sh --fpm-nginx --build
# Quick mode (skip slow tests)
./tests/unit/run-matrix-tests.sh --quick
Matrix Configuration
The matrix tests cover:
- PHP Versions: 8.2, 8.3, 8.4, 8.5
- Tiers: Slim, Standard, Full
- Image Types: php-fpm, php-fpm-nginx
Test Utilities
Shared test utilities are in tests/e2e/lib/test-utils.sh:
# Source test utilities
source "$SCRIPT_DIR/../lib/test-utils.sh"
# Available functions:
log_section "Test Section Name"
log_info "Information message"
log_success "Test passed"
log_fail "Test failed"
log_warn "Warning message"
# Assertions
assert_http_code "$URL" 200 "Health endpoint"
assert_http_contains "$URL" "expected text" "Response content"
assert_file_exists "$CONTAINER" "/path/to/file" "File description"
assert_dir_exists "$CONTAINER" "/path/to/dir" "Directory description"
assert_exec_succeeds "$CONTAINER" "command" "Command description"
# Docker Compose helpers
wait_for_healthy "$CONTAINER_NAME" 60 # Wait up to 60 seconds
cleanup_compose "$COMPOSE_FILE" "$PROJECT_NAME"
get_e2e_root # Returns E2E test root directory
# Summary
print_summary # Print test summary with pass/fail counts
Writing New Tests
1. Create Test Scenario
Create a new file in tests/e2e/scenarios/test-{name}.sh:
#!/bin/bash
# E2E Test: Description of your test
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/test-utils.sh"
E2E_ROOT="$(get_e2e_root)"
FIXTURE_DIR="$E2E_ROOT/fixtures/{name}"
PROJECT_NAME="e2e-{name}"
CONTAINER_NAME="e2e-{name}-app"
BASE_URL="http://localhost:{port}"
# Cleanup on exit
trap 'cleanup_compose "$FIXTURE_DIR/docker-compose.yml" "$PROJECT_NAME" 2>/dev/null || true' EXIT
log_section "Your Test Name"
# Clean up and start
cleanup_compose "$FIXTURE_DIR/docker-compose.yml" "$PROJECT_NAME" 2>/dev/null || true
docker compose -f "$FIXTURE_DIR/docker-compose.yml" -p "$PROJECT_NAME" up -d
wait_for_healthy "$CONTAINER_NAME" 60
# Your tests here
log_section "Test 1: Description"
assert_http_code "$BASE_URL/health" 200 "Health check"
print_summary
2. Create Fixture Directory
Create tests/e2e/fixtures/{name}/:
mkdir -p tests/e2e/fixtures/{name}/app
3. Create docker-compose.yml
services:
app:
image: ${IMAGE:-ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.3-bookworm}
container_name: e2e-{name}-app
ports:
- "{port}:80"
volumes:
- ./app:/var/www/html
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 5s
timeout: 3s
retries: 5
start_period: 30s
4. Make Executable
chmod +x tests/e2e/scenarios/test-{name}.sh
Local Development Testing
Build and Test Local Image
# Build local image
docker build -f php-fpm-nginx/8.3/debian/bookworm/Dockerfile -t my-test-image:local .
# Run E2E tests against local image
IMAGE=my-test-image:local ./tests/e2e/run-e2e-tests.sh
Interactive Debugging
# Start fixture container
cd tests/e2e/fixtures/laravel
IMAGE=my-test-image:local docker compose up -d
# Shell into container
docker compose exec app sh
# Check logs
docker compose logs -f
# Manual health check
docker compose exec app /usr/local/bin/healthcheck.sh
# Cleanup
docker compose down -v
CI/CD Integration
Tests run automatically in GitHub Actions:
# .github/workflows/test.yml
jobs:
test:
runs-on: linux-latest # Use your CI provider's Linux runner
steps:
- uses: actions/checkout@v4
- name: Build images
run: docker compose build
- name: Run unit tests
run: ./tests/unit/run-matrix-tests.sh
- name: Run E2E tests
run: ./tests/e2e/run-e2e-tests.sh
Troubleshooting Tests
Container Won't Start
# Check container logs
docker logs e2e-laravel-app
# Check if port is in use
lsof -i :8091
Test Timeouts
# Increase wait time
wait_for_healthy "$CONTAINER_NAME" 120 # 2 minutes
Cleanup Stuck Containers
# Force cleanup all E2E containers
docker ps -a | grep 'e2e-' | awk '{print $1}' | xargs docker rm -f
docker network ls | grep 'e2e-' | awk '{print $1}' | xargs docker network rm
Debug Specific Test
# Run with verbose output
VERBOSE=true ./tests/e2e/run-e2e-tests.sh my-image laravel
# Or run test directly
bash -x ./tests/e2e/scenarios/test-laravel.sh
Next Steps
| Topic | Guide |
|---|---|
| Image customization | Extending Images |
| Performance testing | Performance Tuning |
| Security testing | Security Hardening |
| CI/CD setup | Production Deployment |