Testing code which interacts with a subversion repository.
SvnTestCase extends FileSystemTestCase and so inherits all the file system methods and assertions.
Additional methods in SvnTestCase:
createRepo($repo_path)
checkout($repo_path, $to_path)
add($path)
remove($path)
commit($path)
update($path)
lock($path)
unlock($path)
and:
createFixture($name)
dumpStatus($path)
dumpInfo($path)
assertLogPattern(
$pattern,
$working_copy_path,
$args = array('-v'),
$message = '%s')I didn't religiously add every subversion command, just the ones I've actually needed so far.
By default, SvnTestCase assumes an AperiRegistry is being used. A config file would define values for host, user and sandbox dir eg:
<?php
// in file "config.php":
$registry->set('host', trim(`hostname`));
$registry->set('user', trim(`whoami`));
$registry->set('sandbox-dir', '/mnt/sandbox/testing/');
etc..
In the test runner:
<?php
$registry = AperiRegistry::instance();
include('path/to/config.php');
However, requiring the use of AperiRegistry is a bit of an imposition. If you want to substitute your own preferred solution override the methods:
.
My modest athlon 3000 laughs at filesystem fixtures, snaps its fingers at database creates and drops, but runs away yelping when tests interact with a subversion repository. These are orders of magnitude slower than anything else I've ever had to test. Hence SvnTestCase provides a fixture caching mechanism.
Once a subversion fixture — a repository, working copies and files — has been created, everything gets bagged up in a gzip file. On the next test run, the fixture can be unzipped quickly from cache rather than created slowly with svn commands.
What you gain from this depends on the details. Obviously some subversion commands do have to be made and these kinds of tests are never going to be lightning fast. However, if most of the subversion calls you need to make are concerned with fixture set up, and hence are cachable, you should see a big improvement.
Here's how it works in practice. Suppose you need a simple fixture with a svn repository and working copy:
<?php
class TestOfSomething extends SvnTestCase {
function setUp() {
$this->repo_path = $this->sandbox() . 'repo/';
$this->working_copy_path = $this->sandbox() . 'working-copy/';
}
function fooFixture() {
$this->createRepo($this->repo_path);
$this->checkout(
$this->repo_path,
$this->working_copy_path);
}
function testSomething() {
$this->createFixture('fooFixture');
...
...
}
}
The first time the test is run, createFixture() calls the named fixture-creation method (fooFixture). Once the fixture method has done its thing, all the files and dirs are bagged up in a gzip file behind the scenes (you don't need to call anything).
On subsequent test runs, "fooFixture" will not be called. Instead, the test case will extract the fixture quickly from cache.
Only files & dirs which were created in the sandbox dir will be cached. The sandbox path can be obtained by calling $this->sandbox().
Since fixture-creation methods will not be run once the fixture has been cached you should not declare vars in them. The cache can only restore files and dirs.
<?php
function fooFixture() {
$this->bar = new Bar; #!! no!
...
}
A cache will become stale if you edit a fixture method. Use the "r" option to force a rebuild:
$ php test.php -r path/to/test-case.php
Note that fixture-caching can also be turned off with a registry value. See aperiplus/config-sample.php.
You should never put fixture cache files under version control. Fixtures may contain details specific to the machine on which they were built (eg a host name) and so may not work on another.
.
By default the cache dir "fixture-cache/$class_name" is created in the same folder as your derived test case and fixture tarballs are saved here.
<?php
class SvnTestCase extends FileSystemTestCase {
function fixtureStore() {
if( !isset($this->store_dir)) {
$this->store_dir =
dirname($this->_mirror()->getFileName()) .
'/fixture-cache/' .
$this->_mirror()->getName() . '/'; // a ReflectionClass instance
}
return $this->store_dir;
}
After the first test run, you should see a bunch of files in the fixture store path, each named after the corresponding fixture-creation method:
[fixture store path] / [method name].tar.gz
Sometimes the same fixture is used in several, related test cases. With the current simpletest design, the best thing to do is to push the common fixture-creation methods down into an abstract class and extend.
<?php
abstract class FixturesForFooTests extends SvnTestCase {
function fooFixture() {
...
}
function barFixture() {
...
}
...
...
}
class TestOfSomething extends FixturesForFooTests {
function test() {
$this->createFixture('barFixture');
...
...
}
}
However, you should note that the default fixtureStore() path tracks test case class names. This means that multiple copies of the same fixture will be saved, one for every derived test case. That may not really matter but if you want you can override fixtureStore() to ensure that derived test cases all use the same path:
<?php
abstract class FixturesForFooTests extends SvnTestCase {
function fixtureStore() {
if( !isset($this->store_dir)) {
$this->store_dir = dirname(__FILE__) . '/fixture-cache/FixturesForFooTests/';
}
return $this->store_dir;
}
...
...
}