Skip to content

Commit

Permalink
Change EntitiesDbTest class to an abstract test case
Browse files Browse the repository at this point in the history
This allows each database implementation to extend it with a data provider.

Also use groups instead of config to exclude database-specific tests.
  • Loading branch information
theodorejb committed Oct 22, 2024
1 parent 23dff01 commit 987ee2a
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 240 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ jobs:
if: ${{ matrix.php == '8.3' }}

- name: Run PHPUnit
run: vendor/bin/phpunit
run: composer test-mysql
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
},
"scripts": {
"analyze": "psalm",
"test": "phpunit"
"test": "phpunit",
"test-mssql": "phpunit --exclude-group mysql",
"test-mysql": "phpunit --exclude-group mssql"
}
}
128 changes: 32 additions & 96 deletions test/EntitiesDbTest.php → test/DbTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,26 @@

use PeachySQL\PeachySql;
use PHPUnit\Framework\TestCase;
use theodorejb\Phaster\Entities;
use theodorejb\Phaster\Test\src\{DbConnector, Users, LegacyUsers, ModernUsers};
use theodorejb\Phaster\Test\src\{Users, LegacyUsers, ModernUsers};

class EntitiesDbTest extends TestCase
abstract class DbTestCase extends TestCase
{
/**
* @return list<array{0: PeachySql}>
*/
public static function dbProvider(): array
{
$config = DbConnector::getConfig();
$databases = [];

if ($config->testMysql()) {
$databases[] = [DbConnector::getMysqlConn()];
}
abstract public static function dbProvider(): PeachySql;

if ($config->testSqlsrv()) {
$databases[] = [DbConnector::getSqlsrvConn()];
}

return $databases;
}

/**
* @return list<array{0: Users}>
*/
public static function entitiesProvider(): array
public static function entitiesProvider(): Users
{
$list = [];

foreach (self::dbProvider() as $db) {
$list[] = [new Users($db[0])];
}

return $list;
return new Users(static::dbProvider());
}

/**
* @return list<array{0: LegacyUsers}>
*/
public static function legacyUsersProvider(): array
public static function legacyUsersProvider(): LegacyUsers
{
$list = [];

foreach (self::dbProvider() as $db) {
$list[] = [new LegacyUsers($db[0])];
}

return $list;
return new LegacyUsers(static::dbProvider());
}

/**
* @return list<array{0: ModernUsers, 1: PeachySql}>
*/
public static function modernUsersProvider(): array
public function testAddEntities(): void
{
$list = [];

foreach (self::dbProvider() as $db) {
$list[] = [new ModernUsers($db[0]), $db[0]];
}

return $list;
}
$entities = static::entitiesProvider();

/**
* @dataProvider entitiesProvider
*/
public function testAddEntities(Entities $entities): void
{
try {
$entities->addEntities([[
'name' => 'My name',
Expand Down Expand Up @@ -111,11 +60,10 @@ public function testAddEntities(Entities $entities): void
$this->assertSame($users, $entities->getEntitiesByIds($ids));
}

/**
* @dataProvider entitiesProvider
*/
public function testUpdateById(Entities $entities): void
public function testUpdateById(): void
{
$entities = static::entitiesProvider();

try {
// optional properties should still be required when replacing an entity
$entities->updateById(0, [
Expand Down Expand Up @@ -150,11 +98,10 @@ public function testUpdateById(Entities $entities): void
$this->assertSame($newUser, $entities->getEntityById($id));
}

/**
* @dataProvider entitiesProvider
*/
public function testPatchByIds(Entities $entities): void
public function testPatchByIds(): void
{
$entities = static::entitiesProvider();

$users = [
[
'name' => 'Name 1',
Expand Down Expand Up @@ -190,22 +137,19 @@ public function testPatchByIds(Entities $entities): void
$this->assertSame([], $entities->getEntitiesByIds($ids));
}

/**
* @dataProvider entitiesProvider
*/
public function testEmptyQueries(Entities $entities): void
public function testEmptyQueries(): void
{
$entities = static::entitiesProvider();
$ids = $entities->addEntities([]);
$this->assertSame([], $entities->getEntitiesByIds($ids));
$this->assertSame(0, $entities->patchByIds($ids, ['weight' => 10]));
$this->assertSame(0, $entities->deleteByIds($ids));
}

/**
* @dataProvider entitiesProvider
*/
public function testDuplicateError(Entities $entities): void
public function testDuplicateError(): void
{
$entities = static::entitiesProvider();

$users = [
[
'name' => 'Conflicting Name',
Expand All @@ -227,11 +171,10 @@ public function testDuplicateError(Entities $entities): void
}
}

/**
* @dataProvider dbProvider
*/
public function testConstraintError(PeachySql $db): void
public function testConstraintError(): void
{
$db = static::dbProvider();

$user = [
'name' => 'Some Name',
'birthday' => '2001-06-17',
Expand All @@ -250,11 +193,9 @@ public function testConstraintError(PeachySql $db): void
}
}

/**
* @dataProvider entitiesProvider
*/
public function testGetEntities(Entities $entities): void
public function testGetEntities(): void
{
$entities = static::entitiesProvider();
$users = [];

for ($i = 1; $i <= 50; $i++) {
Expand Down Expand Up @@ -286,11 +227,9 @@ public function testGetEntities(Entities $entities): void
$this->assertSame($expected, $actual);
}

/**
* @dataProvider entitiesProvider
*/
public function testCountEntities(Entities $entities): void
public function testCountEntities(): void
{
$entities = static::entitiesProvider();
$users = [];

for ($i = 1; $i <= 20; $i++) {
Expand All @@ -306,11 +245,9 @@ public function testCountEntities(Entities $entities): void
$this->assertSame(10, $actual);
}

/**
* @dataProvider legacyUsersProvider
*/
public function testLegacyUsers(Entities $entities): void
public function testLegacyUsers(): void
{
$entities = static::legacyUsersProvider();
$users = [];

for ($i = 1; $i <= 20; $i++) {
Expand Down Expand Up @@ -340,11 +277,10 @@ public function testLegacyUsers(Entities $entities): void
$this->assertSame([['name' => 'Legacy user 5']], $actual);
}

/**
* @dataProvider modernUsersProvider
*/
public function testModernUsers(Entities $entities, PeachySql $db): void
public function testModernUsers(): void
{
$db = static::dbProvider();
$entities = new ModernUsers($db);
$users = [];

for ($i = 1; $i <= 10; $i++) {
Expand Down
57 changes: 57 additions & 0 deletions test/MssqlDbTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace theodorejb\Phaster\Test;

use PeachySQL\PeachySql;
use PeachySQL\SqlServer;
use theodorejb\Phaster\Test\src\App;

/**
* @group mssql
*/
class MssqlDbTest extends DbTestCase
{
private static ?PeachySql $db = null;

public static function dbProvider(): PeachySql
{
if (!self::$db) {
$c = App::$config;
$conn = sqlsrv_connect($c->getSqlsrvServer(), $c->getSqlsrvConnInfo());

if (!$conn) {
throw new \Exception('Failed to connect to SQL server: ' . print_r(sqlsrv_errors(), true));
}

self::$db = new SqlServer($conn);
self::createTestTable(self::$db);
}

return self::$db;
}

private static function createTestTable(PeachySql $db): void
{
$sql = "
DROP TABLE IF EXISTS UserThings;
DROP TABLE IF EXISTS Users;
CREATE TABLE Users (
user_id INT PRIMARY KEY IDENTITY NOT NULL,
name NVARCHAR(50) NOT NULL UNIQUE,
dob DATE NOT NULL,
weight FLOAT NOT NULL,
isDisabled BIT NOT NULL
)";

$db->query($sql);

$sql = "
CREATE TABLE UserThings (
thing_id INT PRIMARY KEY IDENTITY NOT NULL,
user_id INT NOT NULL,
FOREIGN KEY (user_id) REFERENCES Users(user_id)
)";

$db->query($sql);
}
}
58 changes: 58 additions & 0 deletions test/MysqlDbTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace theodorejb\Phaster\Test;

use PeachySQL\Mysql;
use PeachySQL\PeachySql;
use theodorejb\Phaster\Test\src\App;

/**
* @group mysql
*/
class MysqlDbTest extends DbTestCase
{
private static ?PeachySql $db = null;

public static function dbProvider(): PeachySql
{
if (!self::$db) {
$c = App::$config;
$conn = new \mysqli($c->getMysqlHost(), $c->getMysqlUser(), $c->getMysqlPassword(), $c->getMysqlDatabase());

if ($conn->connect_error !== null) {
throw new \Exception('Failed to connect to MySQL: ' . $conn->connect_error);
}

self::$db = new Mysql($conn);
self::createTestTable(self::$db);
}

return self::$db;
}

private static function createTestTable(PeachySql $db): void
{
$db->query("DROP TABLE IF EXISTS UserThings");
$db->query("DROP TABLE IF EXISTS Users");

$sql = "
CREATE TABLE Users (
user_id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
name VARCHAR(50) NOT NULL UNIQUE,
dob DATE NOT NULL,
weight DOUBLE NOT NULL,
isDisabled BOOLEAN NOT NULL
)";

$db->query($sql);

$sql = "
CREATE TABLE UserThings (
thing_id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
user_id INT NOT NULL,
FOREIGN KEY (user_id) REFERENCES Users(user_id)
)";

$db->query($sql);
}
}
10 changes: 4 additions & 6 deletions test/bootstrap.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
<?php

declare(strict_types=1);

use theodorejb\Phaster\Test\src\{DbConnector, Config, LocalConfig};
use theodorejb\Phaster\Test\src\{App, Config, LocalConfig};

require 'vendor/autoload.php';

if (class_exists(LocalConfig::class)) {
// suppress error when LocalConfig doesn't exist
/** @psalm-suppress MixedArgument */
DbConnector::setConfig(new LocalConfig());
/** @psalm-suppress MixedAssignment */
App::$config = new LocalConfig();
} else {
DbConnector::setConfig(new Config());
App::$config = new Config();
}
8 changes: 8 additions & 0 deletions test/src/App.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace theodorejb\Phaster\Test\src;

class App
{
public static Config $config;
}
Loading

0 comments on commit 987ee2a

Please sign in to comment.