Skip to content

Commit 8e7f8fb

Browse files
authored
Feature/amp postgres (#9)
* Add declare strict types * Add support for amphp/postgres * Check for interface, not class
1 parent 375fa19 commit 8e7f8fb

24 files changed

Lines changed: 254 additions & 75 deletions

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
..
33
/vendor
44
.phpunit.cache
5-
.phpunit.result.cache
5+
.phpunit.result.cache
6+
composer.lock

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## Unreleased Changes
9+
10+
### Added
11+
12+
- Introduces a `Cspray\DatabaseTestCase\AbstractConnectionAdapter` for implementing functionality common across all `Cspray\DatabaseTestCase\ConnectionAdapter` implementations.
13+
- Provides the `Cspray\DatabaseTestCase\AmpPostgresConnectionAdapter` for working with the amphp/postgres library.
14+
15+
### Changed
16+
17+
- The `Cspray\DatabaseTestCase\PdoConnectionAdapter` now extends the new `AbstractConnectionAdapter` and has been simplified.
18+
- Added `declare(strict_types=1)` in all files it was missing.
19+
20+
## [0.1.0](https://github.com/cspray/database-test-case/releases/tag/0.1.0) - 2023-03-02
21+
22+
### Added
23+
24+
- Adds a `Cspray\DatabaseTestCase\DatabaseTestCase` that allows for testing database interactions.
25+
- Adds a `Cspray\DatabaseTestCase\ConnectionAdapter` interface that is responsible for actual calls to an underlying connection.
26+
- Provides a `Cspray\DatabaseTestCase\PdoConnectionAdapter` with support for PostgreSQL databases.
27+
- Provides a mechanism for loading fixtures per test, using the Attribute `#[LoadFixture]` and providing an implementation of `Cspray\DatabaseTestCase\Fixture`.
28+
- Provides a mechanism for retrieving the state of a database table at a given point in time with `Cspray\DatabaseTestCase\DatabaseRepresentation\Table`.

composer.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
"database"
88
],
99
"license": ["MIT"],
10+
"minimum-stability": "beta",
11+
"prefer-stable": true,
1012
"require": {
1113
"php": "^8.2",
1214
"phpunit/phpunit": "^10.0"
1315
},
1416
"require-dev": {
1517
"ext-pdo": "*",
1618
"ext-pdo_pgsql": "*",
19+
"amphp/postgres": "^v2.0.0-beta.2",
1720
"roave/security-advisories": "dev-latest"
1821
},
1922
"autoload": {
@@ -27,6 +30,7 @@
2730
}
2831
},
2932
"suggest": {
30-
"ext-pdo": "To enable the PdoConnectionAdapter"
33+
"ext-pdo": "To enable the PdoConnectionAdapter",
34+
"amphp/postgres": "To enable the AmpPostgresConnectionAdapter"
3135
}
3236
}

docker/php/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ RUN apt-get update -y \
44
&& apt-get upgrade -y
55

66
RUN apt-get install git libsodium-dev libzip-dev libpq-dev -y
7-
RUN docker-php-ext-install sodium zip pdo pdo_pgsql
7+
RUN docker-php-ext-install sodium zip pdo pdo_pgsql pgsql
88

99
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
1010

src/AbstractConnectionAdapter.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Cspray\DatabaseTestCase;
4+
5+
use Cspray\DatabaseTestCase\DatabaseRepresentation\Row;
6+
use Cspray\DatabaseTestCase\DatabaseRepresentation\Table;
7+
use Cspray\DatabaseTestCase\Exception\UnableToGetTable;
8+
use Throwable;
9+
10+
abstract class AbstractConnectionAdapter implements ConnectionAdapter {
11+
12+
final public function loadFixture(Fixture $fixture, Fixture ...$additionalFixture) : void {
13+
/** @var Fixture $f */
14+
foreach ([$fixture, ...$additionalFixture] as $f) {
15+
foreach ($f->getFixtureRecords() as $fixtureRecord) {
16+
$sql = $this->generateInsertSqlForParameters($fixtureRecord);
17+
$parameters = $fixtureRecord->parameters;
18+
$this->executeInsertSql($sql, $parameters);
19+
}
20+
}
21+
}
22+
23+
final public function getTable(string $name) : Table {
24+
try {
25+
$table = Table::forName($name);
26+
foreach ($this->executeSelectAllSql($name) as $row) {
27+
$r = null;
28+
foreach ($row as $col => $val) {
29+
$r = $r === null ? Row::forValue($col, $val) : $r->withValue($col, $val);
30+
}
31+
$table = $table->withRow($r);
32+
}
33+
return $table;
34+
} catch (Throwable $throwable) {
35+
throw new UnableToGetTable(
36+
message: sprintf('Unable to fetch table "%s", please check previous Exception for more details.', $name),
37+
previous: $throwable
38+
);
39+
}
40+
}
41+
42+
protected function generateInsertSqlForParameters(FixtureRecord $fixtureRecord) : string {
43+
$table = $fixtureRecord->table;
44+
$parameters = $fixtureRecord->parameters;
45+
$colsString = implode(
46+
', ',
47+
array_keys($parameters)
48+
);
49+
$paramString = implode(
50+
', ',
51+
array_map(static fn(string $col) => ':' . $col, array_keys($parameters))
52+
);
53+
return <<<SQL
54+
INSERT INTO $table ($colsString)
55+
VALUES ($paramString)
56+
SQL;
57+
}
58+
59+
abstract protected function executeInsertSql(string $sql, array $parameters) : void;
60+
61+
/**
62+
* @return list<array<string, mixed>>
63+
* @throws Throwable
64+
*/
65+
abstract protected function executeSelectAllSql(string $table) : array;
66+
67+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Cspray\DatabaseTestCase;
4+
5+
use Amp\Postgres\PostgresConfig;
6+
use Amp\Postgres\PostgresLink;
7+
use Cspray\DatabaseTestCase\Exception\MissingRequiredComposerPackage;
8+
use function Amp\Postgres\connect;
9+
10+
if (! interface_exists(PostgresLink::class)) {
11+
throw new MissingRequiredComposerPackage('You must install amphp/postgres to use ' . AmpPostgresConnectionAdapter::class);
12+
}
13+
14+
class AmpPostgresConnectionAdapter extends AbstractConnectionAdapter {
15+
16+
private ?PostgresLink $connection = null;
17+
18+
public function __construct(
19+
private readonly ConnectionAdapterConfig $adapterConfig
20+
) {}
21+
22+
public function establishConnection() : void {
23+
$this->connection = connect(
24+
PostgresConfig::fromString(sprintf(
25+
'db=%s host=%s port=%d user=%s pass=%s',
26+
$this->adapterConfig->database,
27+
$this->adapterConfig->host,
28+
$this->adapterConfig->port,
29+
$this->adapterConfig->user,
30+
$this->adapterConfig->password
31+
))
32+
);
33+
}
34+
35+
public function onTestStart() : void {
36+
$this->connection->query('START TRANSACTION');
37+
}
38+
39+
public function onTestStop() : void {
40+
$this->connection->query('ROLLBACK');
41+
}
42+
43+
public function closeConnection() : void {
44+
$this->connection->close();
45+
$this->connection = null;
46+
}
47+
48+
public function getUnderlyingConnection() : PostgresLink {
49+
return $this->connection;
50+
}
51+
52+
protected function executeInsertSql(string $sql, array $parameters) : void {
53+
$statement = $this->connection->prepare($sql);
54+
$statement->execute($parameters);
55+
}
56+
57+
protected function executeSelectAllSql(string $table) : array {
58+
$result = $this->connection->query(sprintf('SELECT * FROM %s', $table));
59+
$rows = [];
60+
while ($row = $result->fetchRow()) {
61+
$rows[] = $row;
62+
}
63+
return $rows;
64+
}
65+
}

src/ConnectionAdapter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types=1);
22

33
namespace Cspray\DatabaseTestCase;
44

src/ConnectionAdapterConfig.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types=1);
22

33
namespace Cspray\DatabaseTestCase;
44

src/DatabaseRepresentation/Row.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types=1);
22

33
namespace Cspray\DatabaseTestCase\DatabaseRepresentation;
44

src/DatabaseTestCase.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types=1);
22

33
namespace Cspray\DatabaseTestCase;
44

@@ -7,9 +7,6 @@
77
use PHPUnit\Framework\TestCase;
88
use ReflectionMethod;
99

10-
/**
11-
*
12-
*/
1310
abstract class DatabaseTestCase extends TestCase {
1411

1512
private static ?ConnectionAdapter $connectionAdapter;

0 commit comments

Comments
 (0)