While creating the FilepathBot
class for my VC implementation I’ve tried to use as much of PHP built-in functions as possible.
In particular the pathinfo
function helps me to get some, well, informations about a given path but, aside for its PHP manual page I could not find much information about the return values and possible exceptions.
Blackbox testing the function
While trying to build a path-parsing function one of the first checks is to make sure that the path itself is a valid path. While the functions file_exits
, is_dir
and realpath
could do the job they all rely on taking absolute paths to do their checks and this is not something the class can use.
The function pathinfo
takes a path, a string actually, and wil return some information about it so it should throw an exception if the argument is not a string, right? Wrong.
// test the expectations
public function testPathinfoThrows(){
$this->setExpectedException('ErrorException');
pathinfo(1); // 1 is an int, not a string
}
And the test will fail because pathinfo
throws no errors at all. It actually returns something too and will do the same for almost any argument I will pass it: it returns .
.
Up-scaling the blackbox testing approach I will use a data-provider in tests to assert that my expectation for pathinfo
to return .
in any strange case is right
public function pathProvider()
{
return array(
array(
'some',
'.'
) ,
array(
'/some',
'/'
) ,
array(
'some/relative/path',
'some/relative'
) ,
array(
'/some/abs/path',
'/some/abs'
) ,
array(
'/some/abs/path/',
'/some/abs'
) ,
array(
1,
'.'
) ,
array(
'.',
'.'
) ,
array(
array() ,
'.'
) ,
array(
array(
'some',
'foo'
) ,
'.'
) ,
array(
(object)'some',
'.'
)
);
}
/**
* @dataProvider pathProvider
*/
public function testForPaths($path, $dirname)
{
$info = pathinfo($path);
$this->assertEquals($dirname, $info['dirname']);
The test will fail for non-string parameters like
---------
8) PathTest::testForPaths with data set #7
ErrorException: pathinfo() expects parameter 1 to be string, array given
#1 /Users/Luca/Dropbox/Developer/WebDeveloper/vhosts/plugins/tad-libs-for-wordpress/tests/unit/PathTest.php:63
---------
9) PathTest::testForPaths with data set #8
ErrorException: pathinfo() expects parameter 1 to be string, array given
#1 /Users/Luca/Dropbox/Developer/WebDeveloper/vhosts/plugins/tad-libs-for-wordpress/tests/unit/PathTest.php:63
---------
10) PathTest::testForPaths with data set #9
ErrorException: pathinfo() expects parameter 1 to be string, object given
which means that int
are treated like strings. It’s good enough for me.
What about other return values?
If not explicitly indicated the pathinfo
function will return information about:
- the path
dirname
- the path
basename
- the path
extension
- the path
filename
What will it output with the exact same parameters? I will leave the error-raising ones out of the tests
There were 7 failures:
---------
1) PathTest::testForPaths with data set #0
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'.'
+'some'
#1 /Users/Luca/Dropbox/Developer/WebDeveloper/vhosts/plugins/tad-libs-for-wordpress/tests/unit/PathTest.php:71
---------
2) PathTest::testForPaths with data set #1
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'.'
+'some'
#1 /Users/Luca/Dropbox/Developer/WebDeveloper/vhosts/plugins/tad-libs-for-wordpress/tests/unit/PathTest.php:71
---------
3) PathTest::testForPaths with data set #2
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'.'
+'path'
#1 /Users/Luca/Dropbox/Developer/WebDeveloper/vhosts/plugins/tad-libs-for-wordpress/tests/unit/PathTest.php:71
---------
4) PathTest::testForPaths with data set #3
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'.'
+'path'
#1 /Users/Luca/Dropbox/Developer/WebDeveloper/vhosts/plugins/tad-libs-for-wordpress/tests/unit/PathTest.php:71
---------
5) PathTest::testForPaths with data set #4
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'.'
+'path'
#1 /Users/Luca/Dropbox/Developer/WebDeveloper/vhosts/plugins/tad-libs-for-wordpress/tests/unit/PathTest.php:71
---------
6) PathTest::testForPaths with data set #5
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'.'
+'1'
#1 /Users/Luca/Dropbox/Developer/WebDeveloper/vhosts/plugins/tad-libs-for-wordpress/tests/unit/PathTest.php:71
---------
7) PathTest::testForPaths with data set #6
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'.'
+''
The failing tests are actually telling me the return values, I will use them in tests the next run and will obtain, when all tests wil pass, a map of return values for a given path combination
public function pathProvider()
{
return array(
array(
'some', // original
'.', // dirname
'some', // basename
null, // extension
'some' // filename
) ,
array(
'/some', // original
'/', // dirname
'some', // basename
null, // extension
'some' // filename
) ,
array(
'some/relative/path', // original
'some/relative', // dirname
'path', // basename
null, // extension
'path' // filename
) ,
array(
'/some/abs/path', // original
'/some/abs', // dirname
'path', // basename
null, // extension
'path' // filename
) ,
array(
'/some/abs/path/', // original
'/some/abs', // dirname
'path', // basename
null, // extension
'path' // filename
) ,
array(
1, // original
'.', // dirname
'1', // basename
null, // extension
'1' // filename
) ,
array(
'.', // original
'.', // dirname
'.', // basename
null, // extension
'' // filename
)
);
}
/**
* @dataProvider pathProvider
*/
public function testForPaths($path, $dirname, $basename, $extension, $filename)
{
$info = pathinfo($path);
$this->assertEquals($dirname, $info['dirname']);
$this->assertEquals($basename, $info['basename']);
if (!is_null($extension)) {
$this->assertEquals($extension, $info['extension']);
}
$this->assertEquals($filename, $info['filename']);
}
That’s enough a map to me to move to my production code.
Could this not be made with some printing to screen?
Yes, absolutely.
But testing practices are made to test functions and methods in batteries and to do so in a consistent manner that skips the whole set-up phase and gives a lot of plus. Just think about testing expectations about Exceptions in a foreach
loop. When in doubt I test.