单数据库单应用场景下,如何用paratest运行Dusk测试并生成4个应用实例?
Got it, let's break down how to get 4 parallel Dusk test instances running with Paratest, even with your single database and app setup. The key here is isolating each parallel process so they don't clash—here's a step-by-step guide:
1. Configure Isolated Databases for Each Parallel Process
Since Dusk tests run in a real browser (external to your app's process), transaction rollbacks won't work for isolation. Instead, we'll create a unique test database for each Paratest process using the PARALLEL_TEST_TOKEN environment variable (automatically set by Paratest, starting from 0).
Update Your phpunit.dusk.xml
Add a dynamic database name and app URL to your config:
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd" bootstrap="bootstrap/paratest_dusk.php" colors="true"> <php> <!-- Unique database per parallel process --> <server name="DB_DATABASE" value="testing_${PARALLEL_TEST_TOKEN}"/> <!-- App URL with dynamic port for Docker network access --> <server name="APP_URL" value="http://app:800${PARALLEL_TEST_TOKEN}"/> <!-- Keep your existing DB credentials (DB_USERNAME, DB_PASSWORD, etc.) --> </php> <!-- Rest of your config... --> </phpunit>
Auto-Create & Migrate Each Database
Create a bootstrap script to initialize the database for each process. Save this as bootstrap/paratest_dusk.php:
<?php require __DIR__.'/../vendor/autoload.php'; $token = getenv('PARALLEL_TEST_TOKEN') ?: 0; $dbName = "testing_{$token}"; // Initialize Laravel app to use Artisan commands $app = require_once __DIR__.'/../bootstrap/app.php'; $kernel = $app->make(Illuminate\Contracts\Console\Kernel::class); $kernel->bootstrap(); // Create the database if it doesn't exist try { \Illuminate\Support\Facades\DB::connection()->statement("CREATE DATABASE IF NOT EXISTS {$dbName}"); } catch (\Exception $e) { die("Failed to create database {$dbName}: {$e->getMessage()}"); } // Run migrations for the isolated database \Illuminate\Support\Facades\Artisan::call('migrate', [ '--force' => true, // Skip confirmation in test environments ]);
2. Assign Unique Ports to Each App Instance
Each parallel Dusk test needs its own app server port to avoid conflicts. Modify your DuskTestCase.php to start the server on a port based on the PARALLEL_TEST_TOKEN:
<?php namespace Tests\Browser; use Laravel\Dusk\TestCase as BaseTestCase; use Facebook\WebDriver\Chrome\ChromeOptions; use Facebook\WebDriver\Remote\RemoteWebDriver; use Facebook\WebDriver\Remote\DesiredCapabilities; abstract class DuskTestCase extends BaseTestCase { use CreatesApplication; protected function baseUrl() { $token = getenv('PARALLEL_TEST_TOKEN') ?: 0; return "http://app:800{$token}"; // Match your Docker app service name } protected function startServer() { if (!static::$serverStarted) { $token = getenv('PARALLEL_TEST_TOKEN') ?: 0; $port = 8000 + (int)$token; static::startArtisanServer($port); static::$serverStarted = true; } } // Rest of your existing DuskTestCase code... }
3. Run the Parallel Tests with the Correct Command
Make sure you specify the Dusk PHPUnit config file in your Paratest command—this ensures all our isolation settings are used:
docker-compose exec app vendor/bin/paratest -p4 -c phpunit.dusk.xml tests/Browser/
Key Notes to Avoid Issues
- Database Permissions: Ensure your database user has permission to create new databases. For MySQL in Docker, grant this with
GRANT CREATE ON *.* TO 'your_user'@'%';. - Docker Network Access: If using the Laravel Dusk Chrome container, confirm it's in the same Docker network as your app container—this lets Chrome reach your app's server via the
http://app:{port}URL. - Port Availability: Ensure ports 8000-8003 aren't occupied in your app container.
- Cleanup (Optional): Add a cleanup step to your bootstrap script or create an Artisan command to drop test databases after runs if needed.
内容的提问来源于stack exchange,提问作者Alexander Lyashov

