VfsStream effective filesystem mocking Sebastian Marek
Prerequisites <ul><li>some experience in unit testing
basic knowledge of PHPUnit </li></ul>
External dependencies <ul><li>database
SOAP
3 rd  party </li></ul>
Filesystem <ul><li>Easy to set up
Many different ways
Not a dependency </li></ul>REALLY!?
Learning by example <?php class  Config { private  $filename ; public function  __construct($filename) { if  (!is_file($fi...
guerrillas <ul><li>setUp and tearDown
prepare upfront </li></ul>http://picasaweb.google.co.uk/catof.airsoft/PartisanRusse#5480348761446205778
guerrillas test case <?php class  ConfigTest  extends  PHPUnit_Framework_TestCase { private  $cacheDir  =  '/tmp/cache' ; ...
guerrillas test case <?php class  ConfigTest  extends  PHPUnit_Framework_TestCase { private  $cacheDir  =  '/tmp/cache' ; ...
guerrillas test case <?php class  ConfigTest  extends  PHPUnit_Framework_TestCase { private  $cacheDir  =  '/tmp/cache' ; ...
guerrillas test case class  ConfigTest  extends  PHPUnit_Framework_TestCase { private  $cacheDir  =  '/tmp/cache' ; privat...
Modern warfare vfsStream <ul><li>mocks away filesystem
uses php stream wrapper </li></ul>http://picasaweb.google.co.uk/dawson.jerome/MCASMiramarAirShow2007#5121760885155756402
vfsStream installation #> pear channel-discover pear.php-tools.net #> pear install pat/vfsStream-alpha
vfsStream - register <?php require_once  'vfsStream/vfsStream.php' // (...) protected  function  setUp() { vfsStream:: set...
vfsStream & PHPUnit <?php class  SomeTest  extends  PHPUnit_Framework_TestCase { protected function  setVfsStream() { @ in...
vfsStream – working with files <?php class  ConfigTest  extends  PHPUnit_Framework_TestCase { /** * @covers Config::__cons...
vfsStream – working with files <?php class  ConfigTest  extends  PHPUnit_Framework_TestCase { /** * @covers Config::__cons...
vfsStream url <?php // (...) public function dumpVfsStreamUrl () { $this ->setVfsStream(); echo  vfsStream::url( 'root/con...
vfsStream – working with dirs <?php class  ConfigTest  extends  PHPUnit_Framework_TestCase { /** * @covers Config::createC...
vfsStream – working with dirs <?php class  ConfigTest  extends  PHPUnit_Framework_TestCase { /** * @covers Config::createC...
vfsStream – working with content <?php class  ConfigTest  extends  PHPUnit_Framework_TestCase { /** * @covers Config::fetc...
vfsStream – file perms new  vfsStreamFile( 'app.ini' , 0644); new  vfsStreamDirectory( '/home' , 0755); vfsStream:: newFil...
vfsStream – file ownership $vfsStreamFile->chown(vfsStream:: OWNER_USER_2 ); $vfsStreamDirectory->chown(vfsStream:: OWNER_...
vfsStream – file ownership <ul><li>vfsStream:: OWNER_ROOT  // 0
vfsStream:: OWNER_USER_1 // 1
vfsStream:: OWNER_USER_2 // 2 </li></ul><ul><li>vfsStream:: GROUP_ROOT  // 0
vfsStream:: GROUP_USER_1 // 1
Upcoming SlideShare
Loading in …5
×

vfsStream - effective filesystem mocking

6,871 views

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,871
On SlideShare
0
From Embeds
0
Number of Embeds
261
Actions
Shares
0
Downloads
28
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide
  • Not full support Helps test things like is_readable(), is_writable() or is_executable() Default file mode 0666 Default dir mode 0777 Subdirs get parents perms
  • vfsStream - effective filesystem mocking

    1. 1. VfsStream effective filesystem mocking Sebastian Marek
    2. 2. Prerequisites <ul><li>some experience in unit testing
    3. 3. basic knowledge of PHPUnit </li></ul>
    4. 4. External dependencies <ul><li>database
    5. 5. SOAP
    6. 6. 3 rd party </li></ul>
    7. 7. Filesystem <ul><li>Easy to set up
    8. 8. Many different ways
    9. 9. Not a dependency </li></ul>REALLY!?
    10. 10. Learning by example <?php class Config { private $filename ; public function __construct($filename) { if (!is_file($filename)) { throw new Exception( &quot;Can't set the filename - it doesn't exists!&quot; ); } $this -> filename = $filename; } public function fetchConfig() { return parse_ini_file( $this -> filename , true ); } public function createCacheDir($directory) { if (!is_dir($directory)) { return mkdir($directory, 0700, true ); } return false ; } }
    11. 11. guerrillas <ul><li>setUp and tearDown
    12. 12. prepare upfront </li></ul>http://picasaweb.google.co.uk/catof.airsoft/PartisanRusse#5480348761446205778
    13. 13. guerrillas test case <?php class ConfigTest extends PHPUnit_Framework_TestCase { private $cacheDir = '/tmp/cache' ; private $configFile = '/tmp/config.ini' ; // (...) /** * @covers Config::__construct */ public function testConstructorSetsConfigFilename() { $config = new Config( $this -> configFile ); $this ->assertAttributeEquals( $this -> configFile , 'filename' , $config); } // (...) }
    14. 14. guerrillas test case <?php class ConfigTest extends PHPUnit_Framework_TestCase { private $cacheDir = '/tmp/cache' ; private $configFile = '/tmp/config.ini' ; // (...) /** * @covers Config::__construct */ public function testConstructorThrowsExceptionWithInvalidConfigFile() { $configFile = '/share/usr/config.ini' ; $this ->setExpectedException( 'Exception' , &quot;Can't set the filename - it doesn't exists!&quot; ); $config = new Config($configFile); } // (...) }
    15. 15. guerrillas test case <?php class ConfigTest extends PHPUnit_Framework_TestCase { private $cacheDir = '/tmp/cache' ; private $configFile = '/tmp/config.ini' ; protected function setUp() { $content = &quot; [section1] key1=value1 key2=value3 [section2] key3=value3 &quot; ; file_put_contents( $this -> configFile , $content); if (!is_dir( $this -> cacheDir )) { mkdir( $this -> cacheDir ); } } // (...) }
    16. 16. guerrillas test case class ConfigTest extends PHPUnit_Framework_TestCase { private $cacheDir = '/tmp/cache' ; private $configFile = '/tmp/config.ini' ; // (...) protected function tearDown() { if (is_dir( $this -> cacheDir )) { rmdir( $this -> cacheDir ); } unlink( $this -> configFile ); } // (...) }
    17. 17. Modern warfare vfsStream <ul><li>mocks away filesystem
    18. 18. uses php stream wrapper </li></ul>http://picasaweb.google.co.uk/dawson.jerome/MCASMiramarAirShow2007#5121760885155756402
    19. 19. vfsStream installation #> pear channel-discover pear.php-tools.net #> pear install pat/vfsStream-alpha
    20. 20. vfsStream - register <?php require_once 'vfsStream/vfsStream.php' // (...) protected function setUp() { vfsStream:: setup ( 'root' ); } // (...)
    21. 21. vfsStream & PHPUnit <?php class SomeTest extends PHPUnit_Framework_TestCase { protected function setVfsStream() { @ include_once 'vfsStream/vfsStream.php' ; if (!class_exists( 'vfsStreamWrapper' )) { $this ->markTestSkipped( 'vfsStream is not available - skipping' ); } else { vfsStream:: setup ( 'root' ); } } public function testSomething() { $this ->setVfsStream(); //(...) } }
    22. 22. vfsStream – working with files <?php class ConfigTest extends PHPUnit_Framework_TestCase { /** * @covers Config::__construct */ public function testConstructorSetsConfigFilename() { $this ->setVfsStream(); vfsStream::newFile( 'config.ini' )->at(vfsStreamWrapper::getRoot()); $config = new Config(vfsStream::url( 'root/config.ini' )); $this ->assertAttributeEquals(vfsStream::url( 'root/config.ini' ), 'filename' , $config); } // (...) }
    23. 23. vfsStream – working with files <?php class ConfigTest extends PHPUnit_Framework_TestCase { /** * @covers Config::__construct */ public function testConstructorThrowsExceptionWithInvalidConfigFile() { $this ->setVfsStream(); $this ->setExpectedException( 'Exception' , &quot;Can't set the filename - it doesn't exists!&quot; ); $config = new Config(vfsStream::url( 'root/config.ini' )); } // (...) }
    24. 24. vfsStream url <?php // (...) public function dumpVfsStreamUrl () { $this ->setVfsStream(); echo vfsStream::url( 'root/config.ini' ); // vfs://root/config.ini } // (...) }
    25. 25. vfsStream – working with dirs <?php class ConfigTest extends PHPUnit_Framework_TestCase { /** * @covers Config::createCacheDir */ public function testCreateCacheDirIfItDoesntExists() { $this ->setVfsStream(); $this ->assertFileNotExists(vfsStream:: url ( 'root/cache' )); vfsStream:: newFile ( 'config.ini' )->at(vfsStreamWrapper:: getRoot ()); $config = new Config(vfsStream:: url ( 'root/config.ini' )); $config->createCacheDir(vfsStream:: url ( 'root/cache' )); $this ->assertFileExists(vfsStream:: url ( 'root/cache' )); } // (...) }
    26. 26. vfsStream – working with dirs <?php class ConfigTest extends PHPUnit_Framework_TestCase { /** * @covers Config::createCacheDir */ public function testDontCreateCacheDirIfItExists() { $this ->setVfsStream(); vfsStream:: newFile ( 'config.ini' )->at(vfsStreamWrapper:: getRoot ()); vfsStream:: newDirectory ( 'cache' )->at(vfsStreamWrapper:: getRoot ()); $this ->assertFileExists(vfsStream:: url ( 'root/cache' )); $config = new Config(vfsStream:: url ( 'root/config.ini' )); $result = $config->createCacheDir(vfsStream:: url ( 'root/cache' )); $this ->assertFalse($result); } // (...) }
    27. 27. vfsStream – working with content <?php class ConfigTest extends PHPUnit_Framework_TestCase { /** * @covers Config::fetchConfig */ public function testFetchConfigReturnsArray() { $this ->setVfsStream(); $content = << < 'EOT' [section1] key1 = value1 [section2] key2 = value2 [section3] key3 = value3 EOT; vfsStream:: newFile ( 'config.ini' )->withContent($content) ->at(vfsStreamWrapper:: getRoot ()); $config = new Config(vfsStream:: url ( 'root/config.ini' )); $result = $config->fetchConfig(); $this ->assertTrue(is_array($result)); $this ->assertEquals(3, count($result)); $this ->assertEquals( array ( 'key1' => 'value1' ), $result[ 'section1' ]); $this ->assertEquals( array ( 'key2' => 'value2' ), $result[ 'section2' ]); $this ->assertEquals( array ( 'key3' => 'value3' ), $result[ 'section3' ]); } }
    28. 28. vfsStream – file perms new vfsStreamFile( 'app.ini' , 0644); new vfsStreamDirectory( '/home' , 0755); vfsStream:: newFile ( 'app.ini' , 0640); vfsStream:: newDirectory ( '/tmp/cache' , 0755); $vfsStreamFile->chmod(0664); $vfsStreamDirectory->chmod(0700);
    29. 29. vfsStream – file ownership $vfsStreamFile->chown(vfsStream:: OWNER_USER_2 ); $vfsStreamDirectory->chown(vfsStream:: OWNER_ROOT ); $vfsStreamFile->chgrp(vfsStream:: GROUP_USER_2 ); $vfsStreamDirectory->chgrp(vfsStream:: GROUP_ROOT );
    30. 30. vfsStream – file ownership <ul><li>vfsStream:: OWNER_ROOT // 0
    31. 31. vfsStream:: OWNER_USER_1 // 1
    32. 32. vfsStream:: OWNER_USER_2 // 2 </li></ul><ul><li>vfsStream:: GROUP_ROOT // 0
    33. 33. vfsStream:: GROUP_USER_1 // 1
    34. 34. vfsStream:: GROUP_USER_2 // 2 </li></ul>
    35. 35. Known limitations <ul><li>umask() is ignored
    36. 36. chmod() , chown() , chgrp(), tempnam() doesn't work with streams
    37. 37. no support for fileatime() and filectime()
    38. 38. realpath() and touch() does not work with any other URLs than pure filenames
    39. 39. Smarty doesn't like it ;( </li></ul>
    40. 40. vfsStream PHPUnit Helper <ul><li>simplified integration with PHPUnit
    41. 41. skips when vfsStream not installed
    42. 42. unified interface </li></ul>
    43. 43. vfsStream PHPUnit Helper <?php class MyClassTest extends PHPUnit_Framework_TestCase { // (...) /** * - It will skip the test if vfsStream is not installed * - It will register vfsStream in default root directory called 'root' * - creates 'tmp' directory in root directory */ public function testCreateDirectoryInDefaultRootDirectory() { $vfsStreamWrapper = new vfsStreamHelper_Wrapper( $this ); $vfsStreamWrapper->createDirectory( &quot;tmp&quot; ); $this ->assertFileExists(vfsStream:: url ( 'root/tmp' )); } // (...) }
    44. 44. vfsStream PHPUnit Helper <?php class MyClassTest extends PHPUnit_Framework_TestCase { // (...) /** * - It will skip the test if vfsStream is not installed * - It will register vfsStream in default root directory called 'root' * - creates empty 'myFile.txt' file in root directory */ public function testCreateEmptyFileInDefaultRootDirectory() { $vfsStreamWrapper = new vfsStreamHelper_Wrapper( $this ); $vfsStreamWrapper->createFile( &quot;myFile.txt&quot; ); $this ->assertFileExists(vfsStream:: url ( 'root/myFile.txt' )); } // (...) }
    45. 45. vfsStream PHPUnit Helper <?php class MyClassTest extends PHPUnit_Framework_TestCase { // (...) /** * - It will skip the test if vfsStream is not installed * - It will register vfsStream in root directory called 'myDir' * - creates 'home' directory in root directory */ public function testCreateDirectoryInCustomRootDirectory() { $vfsStreamWrapper = new vfsStreamHelper_Wrapper( $this , 'myDir' ); $vfsStreamWrapper->createDirectory( &quot;home&quot; ); $this ->assertFileExists(vfsStream:: url ( 'myDir/home' )); } // (...) }
    46. 46. vfsStream PHPUnit Helper <?php class MyClassTest extends PHPUnit_Framework_TestCase { // (...) /** * - It will skip the test if vfsStream is not installed * - It will register vfsStream in default root directory called 'root' * - creates directory in different possible ways */ public function testDifferentWaysOfCreatingDirectories() { $vfsStreamWrapper = new vfsStreamHelper_Wrapper( $this ); // create a single directory $vfsStreamWrapper->createDirectory( &quot;tmp&quot; ); // create nested directories $vfsStreamWrapper->createDirectory( &quot;home/proofek/downloads&quot; ); // create a directory using vfsStreamHelper_Directory in default root $vfsStreamWrapper->createDirectory( new vfsStreamHelper_Directory( 'etc' )); // create a directory using vfsStreamHelper_Directory in a subdirectory $vfsStreamWrapper->createDirectory( new vfsStreamHelper_Directory( 'init.d' , 'etc' ) ); // (...)
    47. 47. vfsStream PHPUnit Helper // (...) // create multiple directories $vfsStreamWrapper->createDirectory( array ( new vfsStreamHelper_Directory( 'user1' , 'home' ), new vfsStreamHelper_Directory( 'user2' , 'home' ), new vfsStreamHelper_Directory( 'usr' ), ) ); } // (...) }
    48. 48. vfsStream PHPUnit Helper <?php class MyClassTest extends PHPUnit_Framework_TestCase { // (...) /** * - It will skip the test if vfsStream is not installed * - It will register vfsStream in default root directory called 'root' * - creates files in different possible ways */ public function testDifferentWaysOfCreatingFiles() { $vfsStreamWrapper = new vfsStreamHelper_Wrapper( $this ); // create a single empty file in default root directory $vfsStreamWrapper->createFile( &quot;myFile.txt&quot; ); // create a single empty file using vfsStreamHelper_File in default root $vfsStreamWrapper->createFile( new vfsStreamHelper_File( 'anotherFile.txt' ) ); // create a single file with contents using vfsStreamHelper_File in default root $fileContent = &quot;First line in the file Second line in the file &quot; ; $vfsStreamWrapper->createFile( new vfsStreamHelper_File( 'thirdFile.txt' , $fileContent) ); // (...)
    49. 49. vfsStream PHPUnit Helper // (...) // create a single file with contents using vfsStreamHelper_File in // a subdirectory $fileContent = &quot;First line in the file Second line in the file &quot; ; $vfsStreamWrapper->createDirectory( &quot;tmp&quot; ); $vfsStreamWrapper->createFile( new vfsStreamHelper_File( 'file.txt' , $fileContent, 'tmp' ) ); // create multiple files $vfsStreamWrapper->createDirectory( &quot;etc&quot; ); $vfsStreamWrapper->createFile( array ( new vfsStreamHelper_File( 'file1.txt' , 'some content' , 'etc' ), new vfsStreamHelper_File( 'file2.txt' , null , 'etc' ), new vfsStreamHelper_File( 'file3.txt' ), ) ); } // (...) }
    50. 50. Need help? Resources <ul><li>http://code.google.com/p/bovigo/wiki/vfsStream
    51. 51. http://www.php.net/manual/en/book.stream.php
    52. 52. http://github.com/proofek/vfsStreamHelper </li></ul>Me <ul><li>twitter - @proofek
    53. 53. github - http://github.com/proofek </li></ul>

    ×