{"id":21194444,"url":"https://github.com/cspray/database-test-case","last_synced_at":"2025-03-14T21:28:19.591Z","repository":{"id":98249491,"uuid":"608617515","full_name":"cspray/database-test-case","owner":"cspray","description":"A PHPUnit TestCase for testing database interactions","archived":false,"fork":false,"pushed_at":"2024-04-05T13:34:07.000Z","size":38,"stargazers_count":1,"open_issues_count":9,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-14T20:57:52.651Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cspray.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-03-02T11:48:28.000Z","updated_at":"2023-03-02T15:09:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"f1a1ec76-026f-4c97-84d2-1cea1289284d","html_url":"https://github.com/cspray/database-test-case","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cspray%2Fdatabase-test-case","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cspray%2Fdatabase-test-case/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cspray%2Fdatabase-test-case/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cspray%2Fdatabase-test-case/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cspray","download_url":"https://codeload.github.com/cspray/database-test-case/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243648336,"owners_count":20324858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-20T19:22:11.833Z","updated_at":"2025-03-14T21:28:19.562Z","avatar_url":"https://github.com/cspray.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DatabaseTestCase\n\nA library to facilitate testing database interactions using PHPUnit 10+.\n\nFeatures this library currently provides:\n\n- Handles typical database setup and teardown\n- Simple representation of a table's rows\n- Mechanism for loading fixture data specific to each test\n\nFeatures this library **does not** currently provide, but plans to:\n\n- Semantic assertions on the state of a database\n- Representation for the information schema of a given table\n\nThe rest of this document details how to install this library, make use of its `TestCase`, and what database \nconnection objects are supported out-of-the-box.\n\n## Installation\n\n[Composer](https://getcomposer.org/) is the only supported method for installing this library.\n\n```\ncomposer require --dev cspray/database-test-case\n```\n\n## Usage Guide\n\nUsing this library starts by creating a PHPUnit test that extends `Cspray\\DatabaseTestCase\\DatabaseTestCase`. This class \noverrides various setup and teardown functions provided by PHPUnit to ensure that a database connection is established \nand that database interactions happen against a known state. The `DatabaseTestCase` requires implementations \nto provide a `Cspray\\DatabaseTestCase\\ConnectionAdapter`. This implementation is ultimately responsible for calls to the \ndatabase required by the testing framework. The `ConnectionAdapter` also provides access to the underlying connection, \nfor example a `PDO` instance, that you can use in your code under test. Check out the section titled \"Database Connections\" \nfor `ConnectionAdapter` instances supported out-of-the-box and how you could implement your own.\n\nIn our example, going to assume that you have a PostgreSQL database with a table that has \nthe following DDL:\n\n```postgresql\nCREATE TABLE my_table (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    username VARCHAR(255),\n    email VARCHAR(255),\n    is_active BOOLEAN\n)\n```\n\nNow, we can write a series of tests that interact with the database.\n\n```php\n\u003c?php declare(strict_types=1);\n\nnamespace Cspray\\DatabaseTestCase\\Demo;\n\nuse Cspray\\DatabaseTestCase\\DatabaseRepresentation\\Row;use Cspray\\DatabaseTestCase\\DatabaseTestCase;\nuse Cspray\\DatabaseTestCase\\LoadFixture;use Cspray\\DatabaseTestCase\\SingleRecordFixture;use PDO;\n\nclass MyDemoTest extends DatabaseTestCase {\n\n    // Generally speaking you shouldn't call this method yourself!\n    protected static function getConnectionAdapter() : ConnectionAdapter {\n        // Be sure to change these configuration values to match your test setup!\n        return new PdoConnectionAdapter(\n            new ConnectionAdapterConfig(\n                database: 'postgres',\n                host: 'localhost',\n                port: 5432,\n                user: 'postgres',\n                password: 'postgres'\n            ),\n            PdoDriver::Postgresql\n        );\n    }\n    \n    public function testUnderlyingConnection() : void {\n        // You'd pass the value of this method into your code under test\n        // Use a different ConnectionAdapter if you aren't working with PDO!\n        self::assertInstanceOf(PDO::class, self::getUnderlyingConnection());\n    }\n    \n    public function testShowEmptyTable() : void {\n        // DatabaseTestCase provides a method to get a representation of a database table\n        $table = $this-\u003egetTable('my_table');\n        \n        // The $table is Countable, the count represents the number of rows in the table\n        self::assertCount(0, $table);\n        \n        // The $table is iterable, each iteration yields a Row, but our database is empty!\n        self::assertSame([], iterator_to_array($table));\n    }\n    \n    // Pass any number of Fixture to have corresponding FixtureRecords inserted into \n    // the database before your test starts\n    #[LoadFixture(\n        new SingleRecordFixture('my_table', ['username' =\u003e 'cspray', 'email' =\u003e 'cspray@example.com', 'is_active' =\u003e true]),\n        new SingleRecordFixture('my_table', ['username' =\u003e 'dyana', 'email' =\u003e 'dyana@example.com', 'is_active' =\u003e true])\n    )]\n    public function testLoadingFixtures() : void {\n        $table = $this-\u003egetTable('my_table');\n        \n        self::assertCount(2, $table);\n        self::assertContainsOnlyInstancesOf(Row::class, iterator_to_array($table));\n        self::assertSame('cspray', $table-\u003egetRow(0)-\u003eget('username'));\n        self::assertSame('dyana@example.com', $table-\u003egetRow(1)-\u003eget('email'));\n        self::assertNull($table-\u003egetRow(2));\n    }\n    \n}\n```\n\n### TestCase Hooks\n\nThere are several critical things the `DatabaseTestCase` must take care of for database tests to work properly. To do that \nwe must do something in all the normally used PHPUnit `TestCase` hooks. To be clear those methods are:\n\n- `TestCase::setUpBeforeClass`\n- `TestCase::setUp`\n- `TestCase::tearDown`\n- `TestCase::tearDownAfterClass`\n\nTo make sure that `DatabaseTestCase` processes these hooks correctly they have been marked as `final`. There are new \nmethods that have been provided that allow for the same effective hooks.\n\n| Old Hook | New Hook                       |\n| --- |--------------------------------|\n| `TestCase::setUpBeforeClass` | `DatabaseTestCase::beforeAll`  |\n| `TestCase::setUp` | `DatabaseTestCase::beforeEach` |\n| `TestCase::tearDown` |  `DatabaseTestCase::afterEach` |\n| `TestCase::tearDownAfterClass` | `DatabaseTestCase::afterAll`   |\n\n## Database Connections\n\n| Connection Adapter                                     | Connection Instance         | Library                           | Database  | Implemented | \n|--------------------------------------------------------|-----------------------------|-----------------------------------|-----------|------------|\n| `Cspray\\DatabaseTestCase\\PdoConnectionAdapter`         | `PDO`                       | [PHP PDO][pdo]                    | PostgreSQL | :white_check_mark: |\n| `Cspray\\DatabaseTestCase\\PdoConnectionAdapter`         | `PDO`                       | [PHP PDO][pdo]                    | MySQL     | :white_check_mark: |\n| `Cspray\\DatabaseTestCase\\AmpPostgresConnectionAdapter` | `Amp\\Postgres\\PostgresLink` | [amphp/postgres@^2][amp-postgres] | PostgreSQL | :white_check_mark: | \n| |  `Amp\\Mysql\\MysqlLink`      | [amphp/mysql@^3][amp-mysql]  | MySQL | :x:                |\n\n[amp-mysql]: https://github.com/amphp/mysql\n[amp-postgres]: https://github.com/amphp/postgres\n[pdo]: https://php.net/pdo","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcspray%2Fdatabase-test-case","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcspray%2Fdatabase-test-case","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcspray%2Fdatabase-test-case/lists"}