Testing classes which interact with the filesystem.
This class extends AperiTestCase, adding some new assertions and features which help with filesystem fixtures.
sandbox() - returns the path to the sandbox dir (see below)
createDir($path) - creates intermediate dirs in the path when they don't exist
like unix mkdir -pcreateFile( - creates intermediate dirs in the path when they don't exist
$path,
$contents = '',
$mode = 'w')edit(
$path,
$contents = '',
$mode = 'w')createLink( - creates intermediate dirs in the path when they don't exist
$target,
$link)cache($path) - Add a given path to the stat cache. You could simply write
"filetype($path);" (or etc) but that would not explain the
intent so well.
If you are wondering which of the php stat-cache-inducing
methods are called by cache() the answer is all of them.
Remember that the stat cache stores literal strings: relative
and absolute forms of the same path are seen as two different
paths.
To clear the cache just call clearstatcache(), as normal.
Note that clearstatcache() is always called by the test
framework before setup(). Also, an unlink() call will always
clear all records in the cache (not just the unlinked path).dumpFile($path) - useful for debugging
assertPath( - a clearstatcache() call ensures that the filesystem
$path, is checked and not the stat cache
$type = '', - optionally specify the type (file, link, or dir)
$message = '%s')assertNoPath( - ditto
$path,
$message = '%s')assertEmpty(
$path, - $path is a directory path (rename "assertEmptyDir" ?)
$message = '%s')assertContents(
$path,
$expected, - the full file_get_contents string
$message = '%s')assertContains(
$path,
$needle, - $needle is a text string not a regex
$count = '>=1', - optionally specify num matches (integer) default is one or more
$message = '%s')
At present, all path args are masked to the sandbox path. I'm having second thoughts about that though. What do you think?
The sandbox parent dir must be writable by the php process (so you can create the sandbox...) but the dir above that should not. In the worst case, you might be testing some kind of recursive delete which goes haywire, escapes the sandbox, and tries to delete all your files. Permissions help to prevent this. On windows, the safest thing to do is to set aside a small partition for testing only. Neither is foolproof.
By default the class gets the sandbox path from an AperiRegistry instance. A config file would define a sandbox dir:
<?php
// this is the only registry key used by FileSystemTestCase
$registry->set('sandbox-dir', '/mnt/sandbox/testing/');
etc..
etc..
A tmpfs filesystem would be a good option for the sandbox.
Load everything up in the test runner:
<?php
$registry = AperiRegistry::instance();
include('path/to/config.php');
Requiring the use of AperiRegistry is a bit of an imposition. You can substitute your own preferred solution simply by overriding the method: FileSystemTestCase::sandbox().
A test case might look something like this:
<?php
class YourTestCase extends FileSystemTestCase {
function setUp() {
$this->path = $this->sandbox() . 'a.txt';
$this->createFile($this->path, 'foo');
}
function test() {
$editor = new ChangeFooToBar;
$editor->edit($this->path);
$this->assertContents($this->path, 'bar');
}
A sandbox dir is automatically created before setUp() and destroyed after tearDown(). You don't need to clear up any files or dirs. That's all done for you, provided that they were created in the sandbox...
Fatal errors mean that the script will exit without having a chance to clear up. Abandoned fixtures will be identified and removed the next time the script is run.
"Sandbox path exists" is a skip condition (unless this is an old fixture left behind by a fatal error). Hence, if the sandbox path has mistakenly been set to something catastrophic like c: or "/" FileSystemTestCase will not attempt to delete all your files at tearDown().
The test case will also skip if the sandbox parent dir is not writable.