Skip to content

Commit

Permalink
add support for attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
Ondřej Ešler committed Jun 25, 2024
1 parent 41b1ff5 commit fd966a4
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 52 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Simple DB fixtures loading, replacement for phpunit/dbunit
## Usage
```php
use IW\PHPUnit\DbFixtures\DbFixturesTrait;
use IW\PHPUnit\DbFixtures\Fixtures;

final class MyTest extends TestCase
{
Expand All @@ -17,10 +18,8 @@ final class MyTest extends TestCase
'elastic' => new Elasticsearch\Client(...),
};
}

/**
* @fixtures mysql read-only fixtures.yml
*/

#[Fixtures('mysql', 'read-only', 'fixtures.yml')]
public function testWithFixtures() {
// before test data from fixtures.yml will be loaded into mysql
}
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
}
],
"require": {
"php": ">=8.1",
"phpunit/phpunit": "^9.5||^10.0||^11.0"
"php": ">=8.3",
"phpunit/phpunit": "^11.0"
},
"suggest": {
"opensearch-project/opensearch-php" : "Needed for OpenSearch support",
Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: '2'
services:
mysql:
image: mysql:8.0
Expand Down
59 changes: 30 additions & 29 deletions src/DbFixturesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
use OpenSearch;
use PDO;
use stdClass;
use ReflectionMethod;
use Symfony\Component\Yaml\Yaml;
use PHPUnit\Framework\Attributes\Before;
use PHPUnit\Metadata\Annotation\Parser\Registry;
use PHPUnit\Util\Test;

const AVAILABLE_MODES = ['read-only', 'write'];
use PHPUnit\Event\Facade as EventFacade;

trait DbFixturesTrait
{
Expand Down Expand Up @@ -40,44 +40,45 @@ abstract protected function getConnection(string $connectionName) : mixed;
*/
#[Before]
public function loadFixturesByAnnotations(): void {
if (method_exists(Test::class, 'parseTestMethodAnnotations')) {
$annotations = $annotations = Test::parseTestMethodAnnotations(
static::class,
$this->getName(false)
)['method'] ?? [];
} else {
$annotations = Registry::getInstance()->forMethod(
static::class,
$this->name()
)->symbolAnnotations();
}
$annotations = Registry::getInstance()->forMethod(
static::class,
$this->name()
)->symbolAnnotations();

$fixtures = [];
foreach ($annotations['fixtures'] ?? [] as $fixture) {
[$connectionName, $mode, $args] = \explode(' ', $fixture, 3) + [null, null, null];
[$connectionName, $mode, $files] = \explode(' ', $fixture, 3) + [null, null, null];

if (!in_array($mode, AVAILABLE_MODES)) {
throw new \UnexpectedValueException(
sprintf('Wrong or missing mode of the fixture. Available modes [%s].', implode(', ', AVAILABLE_MODES))
);
$fixture = new Fixtures($connectionName, $mode, ...explode(' ', $files));

if (isset($fixtures[$connectionName])) {
$fixture = $fixture->mergeWith($fixtures[$connectionName]);
}

if (array_key_exists($connectionName, $fixtures)) {
[$newMode, $newArgs] = $fixtures[$connectionName];
$params = [$newMode, $newArgs.' '.$args];
} else {
$params = [$mode, $args];
$fixtures[$connectionName] = $fixture;

EventFacade::emitter()->testTriggeredPhpunitDeprecation(
$this->valueObjectForEvents(),
'Annotation @fixtures is deprecated, use attribute Fixtures instead',
);
}

foreach ((new ReflectionMethod($this, $this->name()))->getAttributes(Fixtures::class) as $attribute) {
$fixture = $attribute->newInstance();

if (isset($fixtures[$fixture->label])) {
$fixture = $fixture->mergeWith($fixtures[$fixture->label]);
}

$fixtures[$connectionName] = $params;
$fixtures[$fixture->label] = $fixture;
}

foreach ($fixtures as $connectionName => [$mode, $args]) {
foreach ($fixtures as $connectionName => $fixture) {
$mode = $fixture->mode;

$filenames = [];
if ($args) {
foreach (\explode(' ', $args) as $filename) {
$filenames[] = $this->resolveFilePath($connectionName, $filename);
}
foreach ($fixture->files as $filename) {
$filenames[] = $this->resolveFilePath($connectionName, $filename);
}

$cache = $this->getCache();
Expand Down
33 changes: 33 additions & 0 deletions src/Fixtures.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php declare(strict_types=1);

namespace IW\PHPUnit\DbFixtures;

use Attribute;

#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
final readonly class Fixtures
{
public array $files;

public function __construct(public string $label, public string $mode, string ...$files) {
assert(!empty($label), 'No label given');
assert(in_array($mode, ['read-only', 'write']), 'Mode must be either "read-only" or "write"');
assert(!empty($files), 'No fixture files given');

foreach ($files as $file) {
assert(!empty($file), 'Empty fixture file given');
}

$this->files = $files;
}

public function mergeWith(Fixtures $fixtures) : Fixtures {
assert($fixtures->label === $this->label, 'Cannot merge fixtures with different labels');

return new Fixtures(
$this->label,
in_array('write', [$fixtures->mode, $this->mode]) ? 'write' : 'read-only',
array_values(array_unique(array_merge($fixtures->files, $this->files))),
);
}
}
16 changes: 16 additions & 0 deletions tests/FixturesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php declare(strict_types=1);

namespace IW\PHPUnit\DbFixtures;

use PHPUnit\Framework\TestCase;

final class FixturesTest extends TestCase
{
public function testCreate() : void {
$fixtures = new Fixtures('mysql', 'write', 'foo.yaml', 'bar.json');

$this->assertSame('mysql', $fixtures->label);
$this->assertSame('write', $fixtures->mode);
$this->assertSame(['foo.yaml', 'bar.json'], $fixtures->files);
}
}
33 changes: 17 additions & 16 deletions tests/UsageOfDbFixturesTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
namespace IW\PHPUnit\DbFixtures;

use Elasticsearch;
use IW\PHPUnit\DbFixtures\Fixtures;
use MongoDB;
use PDO;
use MongoDB\Client;
use PDO;
use PHPUnit\Framework\Attributes\TestWith;

final class UsageOfDbFixturesTraitTest extends \PHPUnit\Framework\TestCase
{
Expand Down Expand Up @@ -52,6 +54,14 @@ public function provideConnections(): \Generator {
* @testWith ["mysql"]
* ["sqlite"]
*/
public function testBdsWithAnnotations(string $label): void {
$this->testBds($label);
}

#[Fixtures('mysql', 'read-only', 'bds.yml')]
#[Fixtures('sqlite', 'read-only', 'bds.yml')]
#[TestWith(['mysql'])]
#[TestWith(['sqlite'])]
public function testBds(string $connectionName): void {
$connection = $this->getConnection($connectionName);

Expand All @@ -76,10 +86,7 @@ public function testBds(string $connectionName): void {
$this->assertSame($expected, $demo);
}

/**
* @fixtures mongo read-only bds.json
*
*/
#[Fixtures('mongo', 'read-only', 'bds.json')]
public function testBdsMongo(): void {
$database = $this->getConnection('mongo');
$fieldCollection = $database->selectCollection('user');
Expand Down Expand Up @@ -121,13 +128,10 @@ public function testBdsMongo(): void {
$this->assertSame($expected, $foundDocuments);
}

/**
* @fixtures sqlite read-only bds.yml fixtures.yml fixtures.yaml
* @fixtures mysql read-only bds.yml fixtures.yml fixtures.yaml
*
* @testWith ["mysql"]
* ["sqlite"]
*/
#[Fixtures('mysql', 'read-only', 'bds.yml', 'fixtures.yml', 'fixtures.yaml')]
#[Fixtures('sqlite', 'read-only', 'bds.yml', 'fixtures.yml', 'fixtures.yaml')]
#[TestWith(['mysql'])]
#[TestWith(['sqlite'])]
public function testLoadingFixtures(string $connectionName): void {
$connection = $this->getConnection($connectionName);

Expand All @@ -152,10 +156,7 @@ public function testLoadingFixtures(string $connectionName): void {
$this->assertSame($expected, $demo);
}

/**
* @fixtures mongo read-only fixtures.json
*
*/
#[Fixtures('mongo', 'read-only', 'fixtures.json')]
public function testLoadingFixturesMongo(): void {
$database = $this->getConnection('mongo');
$fieldCollection = $database->selectCollection('field');
Expand Down

0 comments on commit fd966a4

Please sign in to comment.