Throwback is a new testing framework for legacy PHP applications that have never been tested properly in the past and are too old to support PHPUnit.
Like a lot of PHP developers, I frequently work on very outdated code that is not easily testible. Writing actual unit tests is nearly impossible in code like this, and it might be so old that you can't even use PHPUnit.
Throwback is a new simple to use library for testing these applications. You can test your application two ways: through it's command line interface (if it has one) or through your classes and methods (similar to PHPUnit).
Throwback can be used to test a specific command in your application. You can test the output directly, or test how the command maniuplates the database or filesystem.
The goal of Throwback is to be small, simple, and easy to implement. Because it is primarily for older software, it does not require Composer, and only requires PHP 5.1.0 or greater (with a minimal amount of core modules, and no outside userland dependencies). If you wish to configure it with a database, you will need the pdo_pgsql
or pdo_mysql
extensions installed.
As such, Throwback is implemented as a single executable that can live anywhere on your system. You provide it, by way of your $HOME
directory, a configuration file that can inject global parameters or any number of database connections into your tests.
To install Throwback, place the throwback
command from this repository anywhere on your system. You can install it in your $PATH
if you wish so it can be used from anywhere.
After the throwback
command is installed, create a directory in your $HOME
directory named .throwback
. Copy the config.php.template
file from this repository to the .throwback
directory as config.php
. You are required to retain the top level parameters
and databases
keys even if they point to empty arrays.
The parameters
key in the configuration file is for injecting any key-value pair into your tests. This array is executed once at run-time, so you generally can't put dynamically generated values in it. Each test can get a parameter by calling
$this->getParameter('name')
from within the test case.
You can also connect to any number of PostgreSQL or MySQL databases in your tests. The driver
, host
, database
, username
, and password
keys are required for each database you include. The database name (each sub-key of the databases
key) must be unique.
Database connections are lazily instantiated the first time they are called, and are cached to limit the number open connections. Open connections are automatically closed when a test class is done executing.
You can get an active database connection by calling
$this->getDatabase('name')
from within the test case.
You run your tests by running the throwback
command with an optional argument of the directory you wish to test. If no directory is specified, the current working directory is used.
throwback
throwback /path/to/directory/to/test
After installing the Throwback configuration file properly, you can run ./throwback examples
from within the repository to see example test execution.
Throwback borrows from Go's testing philosophy in that every file suffixed with _test.php
in a specific directory is considered a test and executed as so. Each file ending in _test.php
should have a single class in it that extends the ThrowbackTestCase
class that Throwback provides (you can have multiple classes in a single file, but organizing your tests like that makes them harder to manage). Each test class name must be unique within a specific directory.
All public, non-static methods that begin with test
in the class are considered testable.
Because Throwback is aimed at testing legacy applications, you have several methods that make it easy to run a command and test the output.
Use the runCmd()
method to test a command.
runCmd($command, $argv = array())
Runs a system command specified by $command
optionally passing all of the parameters of $argv
to it. Each element of $argv
should be the full parameter passed in. For example, if a command requires the path to a file, $argv
might look like this:
$argv = array('--file-path=/path/to/file');
The runCmd()
method also has a helper method named getCmd()
. The getCmd()
method makes it easy to generate an absolute path to a command so that it can be tested from anywhere.
$command = $this->getCmd(__FILE__, 'import_data.php');
$output = $this->runCmd('php', array($command, '--file-path=/path/to/file', '--verbose'));
The above example would produce a value in $command
similar to:
/var/apps/my-app/commands/import_data.php
The complete command executed would look like this:
php '/var/apps/my-app/commands/import_data.php' '--file-path=/path/to/file' '--verbose'
Obviously, runCmd()
returns the output of the command. What you do with the output is up to you. You can assert that it matches some expected value, or test the database that the command did what it said it would, or both!
Throwback offers a small amount of assertions you can use to assert your tests are correct.
assertEmpty($actual)
Asserts that $actual
is an empty value as tested by PHP's empty()
method.
assertNotEmpty($actual)
Asserts that $actual
is not an empty value as tested by PHP's empty()
method.
assertEquals($expected, $actual)
Asserts that $expected
is exactly equal to $actual
using PHP's ===
operator.
assertNotEquals($expected, $actual)
Asserts that $expected
is exactly not equal to $actual
using PHP's !==
operator.
assertTrue($actual)
Asserts that $actual
is exactly equal to true
using PHP's ===
operator.
assertFalse($actual)
Asserts that $actual
is exactly equal to false
using PHP's ===
operator.
assertContains($haystack, $needle)
Asserts that $haystack
contains $needle
using PHP's strpos()
method. Matching is case sensitive.
Throwback is most definitely for legacy applications. You should be using more modern tactics when starting a new application. However, that's just not possible for a lot of programmers out there managing decade old code. Throwback is a perfect solution to that problem because it works with old versions of PHP and requires very little system integration.
The MIT License (MIT)
Copyright (c) 2014 Vic Cherubini