Skip to content

Commit 5da871f

Browse files
authored
Make library framework-agnostic (#19)
* Make library framework-agnostic * Setup more complete testing solution * Fix erroneous path to phpunit in CI
1 parent e2ea1dd commit 5da871f

File tree

70 files changed

+1469
-1257
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1469
-1257
lines changed

.github/workflows/ci.yml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,24 @@ on:
77
branches: [main]
88

99
jobs:
10-
tests:
10+
unit-testing:
1111
runs-on: ubuntu-latest
1212

1313
steps:
14-
- name: Checkout
15-
uses: actions/checkout@v3
16-
- name: Test
17-
run: docker compose run --rm tests
14+
- uses: actions/checkout@v3
15+
- name: Setup PHP
16+
uses: shivammathur/setup-php@v2
17+
with:
18+
php-version: 8.3
19+
extensions: xdebug
20+
tools: composer:2
21+
- name: Setup problem matchers for PHP
22+
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
23+
- name: Setup problem matchers for PHPUnit
24+
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
25+
- name: Composer
26+
run: composer install
27+
- name: Unit Testing
28+
env:
29+
XDEBUG_MODE: coverage
30+
run: ./vendor/bin/phpunit

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.
22
..
3+
/build
34
/vendor
45
.phpunit.cache
56
.phpunit.result.cache

README.md

Lines changed: 68 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,94 @@
1-
# DatabaseTestCase
1+
# cspray/database-testing
22

3-
A library to facilitate testing database interactions using PHPUnit 10+.
3+
A low-level, framework-agnostic library for setting up a database suitable
4+
for automated tests. This library provides the following features:
45

5-
Features this library currently provides:
6+
- The `Cspray\DatabaseTesting\ConnectionAdapter` interface that defines how this library,
7+
and those that extend it, interact with your database.
8+
- Comprehensive, customizable strategies for cleaning up your database to ensure each
9+
test works with a known state.
10+
- Declare fixtures, sets of database records, that are loaded for each test.
11+
- A simple interface to easily introspect the contents of a database
12+
table in your test suite.
13+
- Database and testing-framework agnostic approach
614

7-
- Handles typical database setup and teardown
8-
- Simple representation of a table's rows
9-
- Mechanism for loading fixture data specific to each test
15+
It cannot be emphasized enough; this library does not provide a turn-key, usable solution
16+
out-of-the-box. If you use this library directly, instead of one of the extensions that
17+
targets a specific database connection and testing framework, you'll need to ensure the
18+
appropriate concrete implementations and framework integration points are created.
1019

11-
Features this library **does not** currently provide, but plans to:
20+
## Complete Libraries
1221

13-
- Semantic assertions on the state of a database
14-
- Representation for the information schema of a given table
22+
Instead of installing this library directly, we recommend that you install one of the
23+
available options from the "Connection Adapter" and "Testing Extension" list. Chances are,
24+
you'll need both. If you don't see your database connection type or testing framework
25+
listed, please submit an issue to this repository!
1526

16-
The rest of this document details how to install this library, make use of its `TestCase`, and what database
17-
connection objects are supported out-of-the-box.
27+
### Connection Adapter
1828

19-
## Installation
29+
- [cspray/database-testing-pdo](https://github.com/cspray/database-testing-pdo)
2030

21-
[Composer](https://getcomposer.org/) is the only supported method for installing this library.
31+
### Testing Extension
2232

23-
```
24-
composer require --dev cspray/database-test-case
25-
```
33+
- [cspray/database-testing-phpunit](https://github.com/cspray/database-testing-phpunit)
2634

27-
## Usage Guide
28-
29-
Using this library starts by creating a PHPUnit test that extends `Cspray\DatabaseTestCase\DatabaseTestCase`. This class
30-
overrides various setup and teardown functions provided by PHPUnit to ensure that a database connection is established
31-
and that database interactions happen against a known state. The `DatabaseTestCase` requires implementations
32-
to provide a `Cspray\DatabaseTestCase\ConnectionAdapter`. This implementation is ultimately responsible for calls to the
33-
database required by the testing framework. The `ConnectionAdapter` also provides access to the underlying connection,
34-
for example a `PDO` instance, that you can use in your code under test. Check out the section titled "Database Connections"
35-
for `ConnectionAdapter` instances supported out-of-the-box and how you could implement your own.
36-
37-
In our example, going to assume that you have a PostgreSQL database with a table that has
38-
the following DDL:
39-
40-
```postgresql
41-
CREATE TABLE my_table (
42-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
43-
username VARCHAR(255),
44-
email VARCHAR(255),
45-
is_active BOOLEAN
46-
)
47-
```
35+
## Quick Example
4836

49-
Now, we can write a series of tests that interact with the database.
37+
This example is intended to reflect what should be capable with this library. We're going to
38+
use PHPUnit as our testing framework, it is ubiquitous and likely the framework you'll start off
39+
using with this library.
5040

5141
```php
5242
<?php declare(strict_types=1);
5343

54-
namespace Cspray\DatabaseTestCase\Demo;
55-
56-
use Cspray\DatabaseTestCase\DatabaseRepresentation\Row;use Cspray\DatabaseTestCase\DatabaseTestCase;
57-
use Cspray\DatabaseTestCase\LoadFixture;use Cspray\DatabaseTestCase\SingleRecordFixture;use PDO;
58-
59-
class MyDemoTest extends DatabaseTestCase {
60-
61-
// Generally speaking you shouldn't call this method yourself!
62-
protected static function getConnectionAdapter() : ConnectionAdapter {
63-
// Be sure to change these configuration values to match your test setup!
64-
return new PdoConnectionAdapter(
65-
new ConnectionAdapterConfig(
66-
database: 'postgres',
67-
host: 'localhost',
68-
port: 5432,
69-
user: 'postgres',
70-
password: 'postgres'
71-
),
72-
PdoDriver::Postgresql
73-
);
74-
}
75-
76-
public function testUnderlyingConnection() : void {
77-
// You'd pass the value of this method into your code under test
78-
// Use a different ConnectionAdapter if you aren't working with PDO!
79-
self::assertInstanceOf(PDO::class, self::getUnderlyingConnection());
80-
}
44+
namespace Cspray\DatabaseTesting\Demo;
45+
46+
use Cspray\DatabaseTesting\DatabaseCleanup\TransactionWithRollback;
47+
use Cspray\DatabaseTesting\Fixture\LoadFixture;
48+
use Cspray\DatabaseTesting\Fixture\SingleRecordFixture;
49+
use Cspray\DatabaseTesting\RequiresTestDatabase;
50+
use Cspray\DatabaseTesting\TestDatabase;
51+
use PHPUnit\Framework\TestCase;
52+
use PDO;
53+
54+
#[RequiresTestDatabase(
55+
// this should be implemented by you or provided by an extension to this library
56+
new MyPdoConnectionAdapterFactory(),
8157

82-
public function testShowEmptyTable() : void {
83-
// DatabaseTestCase provides a method to get a representation of a database table
84-
$table = $this->getTable('my_table');
85-
86-
// The $table is Countable, the count represents the number of rows in the table
87-
self::assertCount(0, $table);
88-
89-
// The $table is iterable, each iteration yields a Row, but our database is empty!
90-
self::assertSame([], iterator_to_array($table));
58+
// you could also use Cspray\DatabaseTesting\DatabaseCleanup\TruncateTables
59+
// or implement your own Cspray\DatabaseTesting\DatabaseCleanup\CleanupStrategy
60+
new TransactionWithRollback()
61+
)]
62+
final class RepositoryTest extends TestCase {
63+
64+
private PDO $pdo;
65+
private MyRepository $myRepository;
66+
67+
protected function setUp() : void {
68+
// be sure to use the connection from TestDatabase! depending on CleanupStrategy,
69+
// using a different connection could wind up with a dirty database state
70+
$this->pdo = TestDatabase::connection();
71+
$this->myRepository = new MyRepository($this->pdo);
9172
}
9273

93-
// Pass any number of Fixture to have corresponding FixtureRecords inserted into
94-
// the database before your test starts
74+
// populate with more appropriate data. recommended to implement your own
75+
// Cspray\DatabaseTesting\Fixture\Fixture to reuse datasets across tests
9576
#[LoadFixture(
96-
new SingleRecordFixture('my_table', ['username' => 'cspray', 'email' => '[email protected]', 'is_active' => true]),
97-
new SingleRecordFixture('my_table', ['username' => 'dyana', 'email' => '[email protected]', 'is_active' => true])
77+
new SingleRecordFixture('my_table', [
78+
'name' => 'cspray',
79+
'website' => 'https://cspray.io'
80+
])
9881
)]
99-
public function testLoadingFixtures() : void {
100-
$table = $this->getTable('my_table');
82+
public function testTableHasCorrectlyLoadedFixtures() : void {
83+
$table = TestDatabase::table('my_table');
10184

102-
self::assertCount(2, $table);
103-
self::assertContainsOnlyInstancesOf(Row::class, iterator_to_array($table));
104-
self::assertSame('cspray', $table->getRow(0)->get('username'));
105-
self::assertSame('[email protected]', $table->getRow(1)->get('email'));
106-
self::assertNull($table->getRow(2));
85+
self::assertCount(1, $table);
86+
87+
self::assertSame('cspray', $table->row(0)->get('name'))
88+
self::assertSame('website', $table->row(0)->get('website'));
10789
}
108-
90+
10991
}
11092
```
11193

112-
### TestCase Hooks
113-
114-
There are several critical things the `DatabaseTestCase` must take care of for database tests to work properly. To do that
115-
we must do something in all the normally used PHPUnit `TestCase` hooks. To be clear those methods are:
116-
117-
- `TestCase::setUpBeforeClass`
118-
- `TestCase::setUp`
119-
- `TestCase::tearDown`
120-
- `TestCase::tearDownAfterClass`
121-
122-
To make sure that `DatabaseTestCase` processes these hooks correctly they have been marked as `final`. There are new
123-
methods that have been provided that allow for the same effective hooks.
124-
125-
| Old Hook | New Hook |
126-
| --- |--------------------------------|
127-
| `TestCase::setUpBeforeClass` | `DatabaseTestCase::beforeAll` |
128-
| `TestCase::setUp` | `DatabaseTestCase::beforeEach` |
129-
| `TestCase::tearDown` | `DatabaseTestCase::afterEach` |
130-
| `TestCase::tearDownAfterClass` | `DatabaseTestCase::afterAll` |
131-
132-
## Database Connections
133-
134-
| Connection Adapter | Connection Instance | Library | Database | Implemented |
135-
|--------------------------------------------------------|-----------------------------|-----------------------------------|-----------|------------|
136-
| `Cspray\DatabaseTestCase\PdoConnectionAdapter` | `PDO` | [PHP PDO][pdo] | PostgreSQL | :white_check_mark: |
137-
| `Cspray\DatabaseTestCase\PdoConnectionAdapter` | `PDO` | [PHP PDO][pdo] | MySQL | :white_check_mark: |
138-
| `Cspray\DatabaseTestCase\AmpPostgresConnectionAdapter` | `Amp\Postgres\PostgresLink` | [amphp/postgres@^2][amp-postgres] | PostgreSQL | :white_check_mark: |
139-
| | `Amp\Mysql\MysqlLink` | [amphp/mysql@^3][amp-mysql] | MySQL | :x: |
14094

141-
[amp-mysql]: https://github.com/amphp/mysql
142-
[amp-postgres]: https://github.com/amphp/postgres
143-
[pdo]: https://php.net/pdo

composer.json

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,29 @@
11
{
2-
"name": "cspray/database-test-case",
3-
"description": "A PHPUnit TestCase for asserting expectations on a database",
2+
"name": "cspray/database-testing",
3+
"description": "",
44
"type": "library",
55
"keywords": [
66
"testing",
77
"database"
88
],
99
"license": ["MIT"],
10-
"minimum-stability": "beta",
1110
"prefer-stable": true,
1211
"require": {
13-
"php": "^8.2",
14-
"phpunit/phpunit": "^10.0"
12+
"php": "^8.3"
1513
},
1614
"require-dev": {
17-
"ext-pdo": "*",
18-
"ext-pdo_pgsql": "*",
19-
"amphp/postgres": "^v2.0.0-beta.2",
15+
"phake/phake": "^4.5",
16+
"phpunit/phpunit": "^11.0",
2017
"roave/security-advisories": "dev-latest"
2118
},
2219
"autoload": {
2320
"psr-4": {
24-
"Cspray\\DatabaseTestCase\\": "src"
21+
"Cspray\\DatabaseTesting\\": "src"
2522
}
2623
},
2724
"autoload-dev": {
2825
"psr-4": {
29-
"Cspray\\DatabaseTestCase\\Tests\\": "tests"
26+
"Cspray\\DatabaseTesting\\Tests\\": "tests"
3027
}
31-
},
32-
"suggest": {
33-
"ext-pdo": "To enable the PdoConnectionAdapter",
34-
"amphp/postgres": "To enable the AmpPostgresConnectionAdapter"
3528
}
3629
}

docker-compose.yml

Lines changed: 0 additions & 55 deletions
This file was deleted.

docker/mysql/Dockerfile

Lines changed: 0 additions & 7 deletions
This file was deleted.

docker/php/Dockerfile

Lines changed: 0 additions & 25 deletions
This file was deleted.

docker/postgres/Dockerfile

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)