VOOZH about

URL: https://deepwiki.com/hypervel/testbench/9.3-package-testing-best-practices

⇱ Package Testing Best Practices | hypervel/testbench | DeepWiki


Loading...
Last indexed: 7 February 2026 (93289f)
Menu

Package Testing Best Practices

This document provides recommendations for structuring package tests, managing dependencies, implementing isolation strategies, and integrating with CI/CD systems when using Hypervel Testbench. These practices are specifically tailored for testing Hypervel/Hyperf packages in the asynchronous coroutine environment.

For information about the TestCase lifecycle and hooks, see Test Lifecycle and Hooks. For coroutine-specific testing details, see Testing Async and Coroutine Code. For custom trait development, see Custom Testing Traits.


Test Structure and Organization

Directory Layout

Tests should be organized in a tests/ directory at the package root, following PSR-4 autoloading conventions:

my-package/
├── src/
│ └── MyPackage/
│ ├── ServiceProvider.php
│ └── MyService.php
├── tests/
│ ├── Feature/
│ │ ├── MyServiceTest.php
│ │ └── HttpIntegrationTest.php
│ ├── Unit/
│ │ └── HelperFunctionsTest.php
│ └── TestCase.php
├── composer.json
└── phpunit.xml

Each package should provide its own TestCase base class that extends Hypervel\Testbench\TestCase and configures package-specific providers and aliases:


Test Category Guidelines:

CategoryPurposeExample Tests
Unit/Isolated class/function testsHelper functions, value objects, pure logic
Feature/Integration tests with applicationHTTP routes, database queries, service interactions
Browser/ (optional)End-to-end browser testsFull user workflows (requires additional tools)

Sources: src/TestCase.php28-110 composer.json30-34


Test Naming Conventions

Follow these naming patterns for consistency and clarity:

PatternExamplePurpose
{Class}Test.phpServiceProviderTest.phpUnit test for specific class
{Feature}Test.phpAuthenticationTest.phpFeature test for functionality
test_{verb}_{expected}test_register_binds_serviceTest method naming
it_{describes_behavior}it_validates_email_formatAlternative test method naming

Diagram: Test Organization Structure

Sources: src/TestCase.php28-34


Dependency Management

Composer Configuration

Define testbench as a dev dependency in your package's composer.json:


Key Dependencies:

PackageVersionPurpose
hypervel/testbench^0.3Core testing infrastructure
phpunit/phpunit^10.0Test framework
mockery/mockery^1.6Mocking library (included in testbench)
symfony/yaml^7.3YAML config parsing (included in testbench)

Sources: composer.json22-29


Provider Registry Management

Use ConfigProviderRegister to control which framework providers are loaded during tests. This improves test performance by only loading necessary services.


Diagram: Provider Loading Strategies

Example: Minimal Provider Loading


Example: Excluding Heavy Providers


Sources: src/TestCase.php63-67 src/Concerns/CreatesApplication.php


Test Isolation Strategies

Per-Test Application Lifecycle

The TestCase creates a fresh application instance for each test method, ensuring isolation. Understanding this lifecycle is crucial for proper test design:


Diagram: Per-Test Application Isolation

Key Isolation Points:

StageIsolation MechanismFile Reference
BootstrapOne-time via $hasBootstrappedTestbench flagsrc/TestCase.php36-43
ApplicationFresh instance in each setUp()src/TestCase.php69-78
RoutesRe-registered in afterApplicationCreated()src/TestCase.php45-51
DatabaseMigrations destroyed in tearDown()src/Concerns/HandlesDatabases.php
QueuePayload callback resetsrc/TestCase.php87

Sources: src/TestCase.php38-88


Database Isolation Patterns

Three primary strategies exist for database test isolation:

1. In-Memory SQLite (Recommended for Speed)


2. Migration Refresh Per Test


3. Transaction Rollback (Fast but Limited)


Isolation Strategy Comparison:

StrategySpeedIsolationDDL SupportBest For
In-Memory SQLite⚡⚡⚡ Fast✅ Complete✅ YesUnit/Feature tests
Migration Refresh⚡⚡ Medium✅ Complete✅ YesComplex schema tests
Transaction Rollback⚡⚡⚡ Fast⚠️ Partial❌ NoData insertion tests only

Sources: src/Concerns/HandlesDatabases.php testbench.yaml1-20


State Management

Clear application state between tests to prevent leakage:


Diagram: State Management and Cleanup

Automatic Cleanup (Built-in):

Manual Cleanup (When Needed):


When to Use reloadApplication():


Sources: src/TestCase.php80-97


Environment Configuration Best Practices

Configuration Layering

Configuration should be layered from least to most specific:


Diagram: Configuration Priority Layers

Package-Level Configuration (testbench.yaml):


Test-Class-Level Configuration:


Test-Method-Level Configuration:


Sources: testbench.yaml1-20 src/TestCase.php63-67


Environment Variables in Tests

Manage environment variables carefully to avoid cross-test contamination:

Best Practice: Use Config Helpers


Testing Environment-Dependent Behavior:


Sources: testbench.yaml4-6


Route Testing Best Practices

Route Definition Patterns

Define routes using the HandlesRoutes trait with appropriate isolation:


Diagram: Route Testing Architecture

Example: Testing API Routes


Example: Testing Web Routes with Middleware


Isolation Principle: Define only routes needed for specific test class. Don't define application-wide routes in every test.

Sources: src/Concerns/HandlesRoutes.php src/TestCase.php50


Performance Optimization

Minimize Bootstrap Overhead

The one-time bootstrap is efficient, but additional optimizations can speed up test suites:


Diagram: Performance Optimization Layers

Example: Shared Expensive Setup


Example: Conditional Migration Loading


Performance Guidelines:

TechniqueImpactWhen to Use
In-memory SQLiteHighMost database tests
Minimal provider loadingMediumUnit tests
Shared fixturesMediumTests with large data
Skip unnecessary migrationsMediumNon-database tests
Parallel test executionHighLarge test suites

Sources: src/TestCase.php36-43 src/TestCase.php99-103


CI/CD Integration

PHPUnit Configuration

Create a phpunit.xml file in your package root:



GitHub Actions Workflow

Example workflow for automated testing:



Docker Testing Environment

For consistent testing across environments:


Docker Compose for testing:


Sources: composer.json22-29


Common Pitfalls and Solutions

Pitfall 1: Provider Registration Order

Problem: Providers registered in wrong order cause missing dependencies.



Pitfall 2: Forgetting Coroutine Context

Problem: Database queries or async operations fail outside coroutine context.



Pitfall 3: State Leakage Between Tests

Problem: Static properties or singletons retain state across tests.



Pitfall 4: Over-Mocking

Problem: Excessive mocking makes tests brittle and disconnected from reality.



Pitfall 5: Ignoring Test Performance

Problem: Test suite takes too long, discouraging frequent testing.


Sources: src/TestCase.php38-88


Package Testing Checklist

Use this checklist when setting up tests for a new package:

Initial Setup

  • Create tests/ directory with PSR-4 autoloading
  • Add testbench to require-dev in composer.json
  • Create package-specific TestCase base class
  • Configure phpunit.xml with appropriate settings
  • Create testbench.yaml for package test configuration

Test Organization

  • Separate unit tests (tests/Unit/) from feature tests (tests/Feature/)
  • Use consistent naming conventions for test files and methods
  • Define only necessary routes per test class
  • Load only required providers for each test type

Isolation and Performance

  • Use in-memory SQLite for database tests
  • Implement proper tearDown for state cleanup
  • Leverage setUpBeforeClass() for expensive one-time setup
  • Configure minimal provider loading for unit tests

CI/CD Integration

  • Set up automated testing workflow (GitHub Actions, GitLab CI, etc.)
  • Configure test matrix for multiple PHP versions
  • Add code coverage reporting
  • Test with both prefer-lowest and prefer-stable dependencies

Documentation

  • Document test setup instructions in README
  • Provide examples of common test patterns
  • Document any special testing requirements
  • Include coverage badge in repository

Sources: composer.json1-51 testbench.yaml1-20 src/TestCase.php28-110

Refresh this wiki

On this page