Skip to content

Commit

Permalink
feat: Added DbContainerBuilder and OpenSearchContainerBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanChepurnyi committed Jan 7, 2025
1 parent df181b0 commit ef435d6
Show file tree
Hide file tree
Showing 21 changed files with 1,003 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/build export-ignore
/tests export-ignore
/.github export-ignore
33 changes: 33 additions & 0 deletions .github/workflows/php-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: PHP Package
on:
push:
pull_request:
jobs:
format-check:
name: Check PSR12 Standarts
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
tools: composer:v2
- run: composer install
shell: bash
- run: composer format:check
shell: bash
tests:
name: Run Tests
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
tools: composer:v2
- run: composer install
shell: bash
- run: composer test
shell: bash
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/vendor/
/composer.lock
/.idea/
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 EcomDev B.V.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
115 changes: 115 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# 🐳 Test-Containers for Quick Magento Development
[![Docker Build](https://github.com/EcomDev/testcontainer-magento-data/actions/workflows/docker-images.yml/badge.svg)](https://github.com/EcomDev/testcontainer-magento-data/actions/workflows/docker-images.yml)
[![PHP Package](https://github.com/EcomDev/testcontainer-magento-data-php/actions/workflows/php-package.yml/badge.svg)](https://github.com/EcomDev/testcontainer-magento-data-php/actions/workflows/php-package.yml)

This package simplifies the process of automated testing with real database and search engine

## ✨ Features

- 📦 **Pre-configured database and search containers**: Instantly spin up containers with ready-to-use Magento data
- ⚙️ **Easy setup and use**: Use PHP package to automatically discard container after tests
- 🎯 **Blazingly Fast**: Container takes only few seconds to start, so you can focus on testing instead of waiting for db initialization

## 📋 Requirements

- **🐳 Docker**: Ensure Docker is installed and operational on your system.

## 📦 Available images

All the available Docker image version can be found in build repository [EcomDev/testcontainer-magento-data](https://github.com/EcomDev/testcontainer-magento-data?tab=readme-ov-file#-available-images)

## Installation

Use composer with `--dev` flag to add it as dependency for your tests
```bash
composer require --dev ecomdev/testcontainers-magento-data
```


## Examples

### MySQL container

Create Latest Magento Database Build
```php
use EcomDev\TestContainers\MagentoData\DbContainerBuilder;

$container = DbContainerBuilder::mysql()
->build();
```

Create Latest Magento Database Build with sample data
```php
use EcomDev\TestContainers\MagentoData\DbContainerBuilder;

$container = DbContainerBuilder::mysql()
->withSampleData()
->build();
```

Create 2.4.7-p2 with sample data and fetch number of products
```php
use EcomDev\TestContainers\MagentoData\DbContainerBuilder;
use PDO;

$container = DbContainerBuilder::mysql()
->withMagentoVersion('2.4.7-p2')
->withSampleData()
->build();

$connectionSettings = $container->getConnectionSettings();
$connection = new PDO(
$connectionSettings->dsn(),
$connectionSettings->user,
$connectionSettings->password
);

$result = $connection->query('SELECT COUNT(*) FROM catalog_product_entity');
// Outputs 2040
echo $result->fetch(PDO::FETCH_COLUMN);
```

### MariaDB container
Everything the same as for MySQL container, just a different builder method

```php
use EcomDev\TestContainers\MagentoData\DbContainerBuilder;

$container = DbContainerBuilder::mariadb()
->withMagentoVersion('2.4.7-p2')
->withSampleData()
->build();
```

## OpenSearch container

For OpenSearch container there is a different builder and container, that allows building base url for http connection

Here is a small example

```php
use EcomDev\TestContainers\MagentoData\OpenSearchContainerBuilder;
use GuzzleHttp\Client;

$container = OpenSearchContainerBuilder::new()
->withSampleData()
->build();

$client = new Client([
'base_uri' => $container->getBaseUrl()
]);

$result = json_decode(
$client->get('magento2_product_1/_count')->getBody()->getContents(),
true
);

// Outputs 181
echo $result['count'];
```

## 📜 License

This project is licensed under the MIT License.

See the [LICENSE](LICENSE) file for more details.
40 changes: 40 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "ecomdev/testcontainers-magento-data",
"description": "TestContainers for Magento data in integration/functional tests",
"type": "library",
"require": {
"php": "^8.3",
"testcontainers/testcontainers": "^0.2.0"
},
"require-dev": {
"phpunit/phpunit": "^11.5",
"ext-pdo": "*",
"brianium/paratest": "^7.7",
"guzzlehttp/guzzle": "^7.0",
"squizlabs/php_codesniffer": "^3.0"
},
"license": "MIT",
"autoload": {
"psr-4": {
"EcomDev\\TestContainers\\MagentoData\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"EcomDev\\TestContainers\\MagentoData\\": "tests"
}
},
"scripts": {
"test": "paratest ./tests/ ",
"unit": "paratest ./tests/ --exclude-group=slow",
"format:check": "phpcs --standard=PSR12 ./",
"format:write": "phpcbf --standard=PSR12 ./"
},
"authors": [
{
"name": "Ivan Chepurnyi",
"email": "ivan.chepurnyi@ecomdev.org"
}
],
"minimum-stability": "stable"
}
Empty file added release-please-config.json
Empty file.
49 changes: 49 additions & 0 deletions src/ContainerBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace EcomDev\TestContainers\MagentoData;

/**
* Interface defining methods for building and configuring containers.
*/
interface ContainerBuilder
{
/**
* Sets the Magento version and returns a new instance with the updated value.
*
* @param string $version The version of Magento to be set.
* @return self A new instance with the specified Magento version.
*/
public function withMagentoVersion(string $version): self;

/**
* Sets the variation and returns a new instance with the updated value.
*
* @param string $variation The variation to be set.
* @return self A new instance with the specified variation.
*/
public function withVariation(string $variation): self;

/**
* Configures the instance to use sample data and returns a new instance with the updated configuration.
*
* @return self A new instance configured to include sample data.
*/
public function withSampleData(): self;

/**
* Builds container with configured input
*/
public function build(): RunningContainer;

/**
* Creates new container with unique identifier or returns existing one with the same id
*
* Helpful for re-using read-only container usage
*/
public function shared(string $id): RunningContainer;

/**
* Returns final image name based on all configuration provided
*/
public function getImageName(): string;
}
56 changes: 56 additions & 0 deletions src/ContainerBuilderConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace EcomDev\TestContainers\MagentoData;

/**
* Provides configuration options for building a container.
*/
trait ContainerBuilderConfiguration
{
/**
* Version of Magento which container is based on
*
* @var string
*/
private string $magentoVersion = 'latest';

/**
* Name of the container variations
*
* @var string
*/
private string $variation = '';

/**
* Sets the Magento version and returns a new instance with the updated value.
*/
public function withMagentoVersion(string $version): self
{
$other = clone $this;
$other->magentoVersion = $version;
return $other;
}

/**
* Sets the variation and returns a new instance with the updated value.
*/
public function withVariation(string $variation): self
{
$other = clone $this;
$other->variation = $variation;
return $other;
}

/**
* Configures the instance to use sample data and returns a new instance with the updated configuration.
*/
public function withSampleData(): self
{
return $this->withVariation('sampledata');
}

private function generateImageTag(): string
{
return $this->magentoVersion . ($this->variation ? '-' . $this->variation : '');
}
}
13 changes: 13 additions & 0 deletions src/ContainerMetadata.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace EcomDev\TestContainers\MagentoData;

final class ContainerMetadata
{
private const CONTAINER_NAME = 'ghcr.io/ecomdev/testcontainer-magento-data/%s';

public static function getImageName(string $type)
{
return sprintf(self::CONTAINER_NAME, $type);
}
}
30 changes: 30 additions & 0 deletions src/ContainerRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace EcomDev\TestContainers\MagentoData;

/**
* A class responsible for managing a registry of running containers,
* identified by their image name and a unique identifier.
*/
final class ContainerRegistry
{
private static array $containers = [];

/**
* Register container with specified id
*/
public static function registerContainer(string $id, RunningContainer $container): RunningContainer
{
$imageName = $container->getImageName();
self::$containers[$imageName][$id] = $container;
return $container;
}

/**
* Returns container by image and id if it was registered before
*/
public static function findContainer(string $image, string $id): ?RunningContainer
{
return self::$containers[$image][$id] ?? null;
}
}
Loading

0 comments on commit ef435d6

Please sign in to comment.