DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Data Engineering
  3. Data
  4. Practical PHP Testing Patterns: Prebuilt Fixture

Practical PHP Testing Patterns: Prebuilt Fixture

Giorgio Sironi user avatar by
Giorgio Sironi
·
Jan. 10, 11 · Interview
Like (0)
Save
Tweet
Share
853 Views

Join the DZone community and get the full member experience.

Join For Free

The goal we want to tackle today is: how to prepare Shared Fixture before the first test runs? There are of course other approaches, like lazy creation, but simply having it always available simplifies the rest of the test suite. For instance, the tests can simply assume the database connection is there.

Another goal of this pattern, Prebuilt Fixture, is reducing overhead; you don't need to open a new database connection for every single test, as you can reuse the same one if you are careful in resetting its state.

Resetting the state of a shared database is covered by other patterns, but how to create that connection for the first time is a simple example of this one.

An important point to keep in mind is not depending on manual creation of the fixture to run your tests: for example, a local database with the updated schema. If you go that way, you will start running your tests less often just to avoid the pain of having to recreate or update that database. Even with Prebuilt Fixtures, you should still be able to run any subset of your test suite at the push of a button.

A last caveat, inherited from Shared Fixtures, is that an immutable fixture is easier to share.

Basically this pattern implements Shared Fixtures which are always built, while the previous one, Implicit Setup, always creates Fresh Fixtures for each test. The next one, Lazy Setup, will deal with fixtures which are not always built, but only when needed.

Implementation

PHPUNit's --bootstrap argument or boostrap attribute in XML configuration is all the fancy technology we need.

Once upon a time, you had to scatter require_once() statements into your test case files because if you ran a test in isolation, it would still have to call the boostrap, for example to setup autoloading.

Now PHPUnit provides the boostrap hook so that every group of tests, from 1 to all the tests in the suite, can be executed after a boostrap file is included. Even when filtering a single test from a Testcase Class, you will still run automatically the bootstrap, once and for all until the phpunit command exits.

In case of framework applications, you'll probable have some code to reuse in the included file. For Zend Framework, instancing a Zend_Application object is the way to go: you can then bootstrap only the resources you want to share between tests, or the whole application for the first time.

Examples

The sample code shows you how a boostrap file looks like and how it can create a Shared Fixture that all tests can use. The only command you need to run the tests is:
phpunit SampleTest.php
or, to execute all the concrete tests (here there is only one):
phpunit

Here's the PHP test code, plus the configuration file. I could have created a small repository on Github, but I think setting up by yourself teaches a lot more than doing a git pull. You can just create these files in an empty directory.

bootstrap.php

<?php
// let's suppose this connection is an Oracle or MySQL one: we want to share it
// between tests
// For SQLite connections, they may have many tables in them, and we do not
// want to recreate all the schema in a new (Fresh Fixture) connection.
$db = new PDO('sqlite::memory:');
require_once 'BaseTest.php';
BaseTest::setDb($db);
// without this, PHPUnit will try to serialize $db in order to backup all global
// variables between tests
unset($db);

phpunit.xml

<!-- defines bootstrap.php as a file to require_once() prior to executing any test suite -->
<phpunit bootstrap="bootstrap.php">
<testsuite>
<directory>./</directory>
</testsuite>
</phpunit>

BaseTest.php

<?php
abstract class BaseTest extends PHPUnit_Framework_TestCase
{
/**
* @var PDO
*/
private static $db;

/**
* We could even check this is called only once, but it could
* be necessary to call it more times in order to reset the connection
* in some corner cases.
*/
public static function setDb(PDO $db)
{
self::$db = $db;
}

/**
* Return the statically-set connection.
* If there is a configuration error and the connection was not initialized,
* we throw immediately an exception to avoid fatal errors, like someone calling
* $db->exec() on null.
*/
protected function getDb()
{
if (self::$db === null) {
throw new Exception('Db was not initialized.');
}

return self::$db;
}
}

SampleTest.php

<?php
class SampleTest extends BaseTest
{
public function testSomeQuery()
{
// the connection has been already initialized
$db = $this->getDb();

$this->assertTrue($db instanceof PDO);
//...
}
}
Fixture (tool) PHP Testing Database connection

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • DevOps for Developers — Introduction and Version Control
  • Simulating and Troubleshooting BLOCKED Threads in Kotlin [Video]
  • How To Select Multiple Checkboxes in Selenium WebDriver Using Java
  • Strategies for Kubernetes Cluster Administrators: Understanding Pod Scheduling

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: