shyim / testcontainer
Testcontainers implementation in PHP
Installs: 15 051
Dependents: 0
Suggesters: 0
Security: 0
Stars: 113
Watchers: 5
Forks: 19
Open Issues: 7
Requires
- php: >= 8.1
- ext-curl: *
- beluga-php/docker-php: ^1.45
Requires (Dev)
- ext-pdo: *
- ext-pdo_mysql: *
- ext-pdo_pgsql: *
- brianium/paratest: ^6.11
- friendsofphp/php-cs-fixer: ^3.12
- phpstan/extension-installer: ^1.2
- phpstan/phpstan: ^1.8
- phpstan/phpstan-phpunit: ^1.1
- phpunit/phpunit: ^9.5
- predis/predis: ^3.0 || ^2.0
README
Testcontainers is a PHP package that makes it simple to create and clean up container-based dependencies for automated integration/smoke tests. The package is inspired by the Testcontainers project for Java.
Installation
Add this to your project with composer
composer req --dev testcontainers/testcontainers
Usage/Examples
Starting a general Container
<?php use Testcontainers\Container\GenericContainer; $container = new GenericContainer('nginx:alpine'); // set an environment variable $container->withEnvironment([ 'key1' => 'val1', 'key2' => 'val2' ]); // enable health check for an container $container->withHealthCheckCommand('curl --fail localhost'); // mount current dir to /var/www/html $container->withMount(__DIR__, '/var/www/html');
Normally you have to wait until the Container is ready. so for this you can define an wait rule:
use Testcontainers\Container\GenericContainer; use Testcontainers\Wait\WaitForExec; use Testcontainers\Wait\WaitForLog; use Testcontainers\Wait\WaitForHttp; use Testcontainers\Wait\WaitForHealthCheck; use Testcontainers\Wait\WaitForHostPort; $container = new GenericContainer('nginx:alpine'); // Run mysqladmin ping until the command returns exit code 0 $container->withWait(new WaitForExec(['mysqladmin', 'ping', '-h', '127.0.0.1'])); $container->withWait(new WaitForExec(['mysqladmin', 'ping', '-h', '127.0.0.1']), function($exitCode, $contents) { // throw exception if process result is bad }); // Wait until that message is in the logs $container->withWait(new WaitForLog('Ready to accept connections')); // Wait for an http request to succeed $container->withWait(new WaitForHttp($port, $method = 'GET', $path = '/')); // Wait for all bound ports to be open $container->withWait(new WaitForHostPort()); // Wait until the docker heartcheck is green $container->withWait(new WaitForHealthCheck());
MySQL
<?php use Testcontainers\Modules\MySQLContainer; $container = (new MySQLContainer('8.0')) ->withMySQLDatabase('foo') ->withMySQLUser('bar', 'baz') ->start(); $pdo = new \PDO( sprintf( 'mysql:host=%s;port=%d', $container->getHost(), $container->getFirstMappedPort() ), 'bar', 'baz', ); // Do something with pdo
MariaDB
<?php use Testcontainers\Modules\MariaDBContainer; $container = $container = (new MariaDBContainer()) ->withMariaDBDatabase('foo') ->withMariaDBUser('bar', 'baz') ->start(); $pdo = new \PDO( sprintf( 'mysql:host=%s;port=%d', $container->getHost(), $container->getFirstMappedPort() ), 'bar', 'baz', ); // Do something with pdo
PostgreSQL
<?php use Testcontainers\Modules\PostgresContainer; $container = (new PostgresContainer()) ->withPostgresUser('bar') ->withPostgresDatabase('foo') ->start(); $pdo = new \PDO( sprintf( 'pgsql:host=%s;port=%d;dbname=foo', self::$container->getHost(), self::$container->getFirstMappedPort() ), 'bar', 'test', ); // Do something with pdo
Redis
use Testcontainers\Modules\RedisContainer; $container = (new RedisContainer()) ->start(); $redis = new \Redis(); $redis->connect($container->getHost(), $container->getFirstMappedPort()); // Do something with redis
OpenSearch
use Testcontainers\Modules\OpenSearchContainer; $container = (new OpenSearchContainer()) ->withDisabledSecurityPlugin() ->start(); // Do something with opensearch
Use with symfony
# config/packages/test/services.yaml parameters: 'doctrine.dbal.connection_factory.class': App\Tests\TestConnectionFactory
namespace App\Tests; use Doctrine\Bundle\DoctrineBundle\ConnectionFactory; use Doctrine\Common\EventManager; use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Tools\DsnParser; use Testcontainers\Modules\PostgresContainer; class TestConnectionFactory extends ConnectionFactory { static $testDsn; public function __construct(array $typesConfig, ?DsnParser $dsnParser = null) { if (!$this::$testDsn) { $psql = (new PostgresContainer()) ->withPostgresUser('user') ->withPostgresPassword('password') ->withPostgresDatabase('database') ->start(); $this::$testDsn = sprintf('postgresql://user:password@%s:%d/database?serverVersion=14&charset=utf8', $psql->getAddress(), $psql->getFirstMappedPort()); } parent::__construct($typesConfig, $dsnParser); } public function createConnection(array $params, ?Configuration $config = null, ?EventManager $eventManager = null, array $mappingTypes = []) { $params['url'] = $this::$testDsn; return parent::createConnection($params, $config, $eventManager, $mappingTypes); } }