PHPã§ãã¤ãã£ãé¢æ°ãå«ãã³ã¼ãã®ãã¹ã¿ããªãã£ãä¸ããï¼ã¤ã®æ¹æ³
PHPã§ãã¹ãã±ã¼ã¹ãä½æããå ´åããã¤ãã£ãé¢æ°ã使ã£ã¦ãããããªã³ã¼ãã«å¯¾ãã¦ãã¹ããå®è¡ãããã¨ããã¨ãã©ããã¦ãç°å¢ã«ä¾åããããå®ãªã½ã¼ã¹ã«ã¢ã¯ã»ã¹ããå¿ è¦ãåºã¦ãã¾ããã¨ãããã¾ãã
ãã®è¨äºã§ã¯ããã®ãããªåé¡ã«å¯¾ãã対å¦æ³ãæ示ãã¾ãã
çµç·¯ã¿ãããªãã®
å
æ¥ãWeb APIãã³ã¼ã«ããPHPã©ã¤ãã©ãªãæ¸ãã¦ããã®ã§ãããHTTPããããé¨åã®ãã¹ããåãé¢ããããããããã¦ãã¾ããã
ã¡ãã£ã¨åã«Perlã®Test::Timeã¨ããã©ã¤ãã©ãªãæãã£ã¦æåãã¦ããã®ã§ãããPHPã§ããã¤ãã£ãé¢æ°ããªã¼ãã¼ã©ã¤ãã§ãããã©ããªã«ãã°ãããã ããããªã©ã¨ã¼ããã¦ããã®ã§ãã
ãããªã¨ãã«ã@takimoã«PHP 5.3ãªããªã¼ãã¼ã©ã¤ãã§ããããã£ã¦è¨ããã¦ãããã¨æãç«ã£ã¦ãã¹ãã«çµã¿è¾¼ãæ¹æ³ãèãã¦ã¿ãã¨ãããå²ã¨ã¹ãã¼ãã«å®ç¾ã§ããããªæ¹æ³ãè¦ã¤ãã£ãã®ã§ãæ¹æ³è«ã®ä¸ææ¡ã¨ãã¦è¨äºã«æ¸ãã¦ã¿ã¾ãã
å²ã¨ã·ã³ãã«ãªè©±ãªã®ã§ãããæ¢ã«èª°ãã確ç«ãã¦ããããæ¹ããããã¾ããããä¹
ã
ã«ããã°ãã¡ããã¨æ¸ãã¨ããç®ç*1ãå«ãã¦æ¸ããã¨ãããããã®ã§è»è¼ªã®åçºæã ã£ããã容赦ãã
ã¾ããPHP 5.4ã§çãä¸ãã£ã¦ããæä¸ã«PHP 5.3ãªè©±ããã¡ãã£ã¦ã¦ç¸å¤ããã空æ°èªãã¦ãªããã©ããã¯ã¹ã«ã¼ã§ã
Thanks inspiration for @takimo !!
ãªã½ã¼ã¹ã«ã¢ã¯ã»ã¹ããé¢æ°ãå«ããã¹ãã®åé¡ç¹
ãã¨ãã°ã以ä¸ã®ãããªãã¸ãã¯ãå«ããªãã¸ã§ã¯ããä½æããã¨ãã¾ãã
- file_get_contents()é¢æ°ã§HTTPãªã½ã¼ã¹ãåå¾ããã
- date()/time()é¢æ°ãDateTimeãªãã¸ã§ã¯ãã使ã£ã¦æéè¨æ¸¬ãããã
- system()é¢æ°ã«ãã£ã¦ã·ã¹ãã ã³ãã³ããå®è¡ããçµæãå¾ãã
ãããã®å¦çã«å ±éããç¹ã¨ãã¦ãããããæ£ããå®è¡çµæãå¾ãããã«ã¯å®éã«ã·ã¹ãã ãªã½ã¼ã¹ã»å¤é¨ãªã½ã¼ã¹ã«å¯¾ãã¦ã¢ã¯ã»ã¹ããçµæãåå¾ããå¿ è¦ããããã¨ããå´é¢ãããã¾ãã
ãã®ãããªå¦çãå«ãã¯ã©ã¹ã«å¯¾ãã¦ãã¹ãã±ã¼ã¹ãä½æããå ´åã該å½é¨åã®çµæãå®è¡ç°å¢ã«ä¾åãããã®ã¨ãªããããå
¨ä½ã¨ãã¦æ£ããçµæãå¾ãããã«ã¯æ¬å½ã«å¤é¨ãªã½ã¼ã¹ã«ã¢ã¯ã»ã¹ããããå¾ã¾ããã
çµæã¨ãã¦ããããã®ãã¹ãèªä½ãç°å¢ã«ä¾åãããã®ã¨ãªãããã¹ãå®è¡æéã®å¢å ãä½è¨ãªè² è·ããã¹ãå®è¡èªä½ã®é£æ度ã®ä¸æãã²ãã¦ã¯èªåãã¹ãã®åç¾æ§ã«æ¯éããããå ´åããåºã¦ãã¾ãã
ãããã®åé¡ã¯ãèªåãã¹ããè¡ãéã«åä»ãªé害ã¨ãªã£ã¦ãã¾ãã¾ãã
ããã«ãã¦åé¿ããã
å
ã
ãPHPã§ã¯ãããã®åé¡ã«å¯¾å¦ããããã«ãã³ã¼ããã®ãã®ã®æ½è±¡åº¦ãä¸å¿
è¦ã«ä¸ããã*2ãç¡çç¢çãããªãrunkitã®ãããªã¨ã¯ã¹ãã³ã·ã§ã³ã§ããªããã¼ãªå¯¾å¿*3ãè¡ããã¨ã«ãã£ã¦æåãå·®ãæ¿ãããçã®å¯¾å¦æ³ããããã¾ããã§ããã
ç¾å®çã«ã¯ãã·ã¹ãã ãªã½ã¼ã¹ã«ä¾åããã¾ã¾å®è¡ãããã¨ãã»ã¨ãã©ã ã¨æãã¾ãã
ã§ãããPHP 5.3ã§åå空éãå°å ¥ããããã¨ã§ãåå空éã®ãã¨ã§ããã°ãã¤ãã£ãé¢æ°ã¨ååã®é¢æ°ãå®ç¾©ãããã¨ãå¯è½ã¨ãªãã¾ããã
ããããã¾ãå¿ç¨ãããã¨ã§ããã¤ãã£ãé¢æ°ãå«ãã³ã¼ãã§ãã·ã¹ãã ã¨ã®ççµåãä¿ã¡ã¤ã¤ããã¸ãã¯å´ã«ä½è¨ãªè² æ ããããã«é©åãªãã¹ãããããããã«ãªãã¾ãã*4
ããã§ã¯ããã®æ¹æ³ã«ã¤ãã¦ãããã£ã¨ããå ´åã¨ãã¡ãã¨ããå ´åã®ï¼ç¨®é¡ã®ãã¿ã¼ã³ãèãã¾ãã
ã±ã¼ã¹ï¼ï¼ ï¼æã®ã©ã¤ãã©ãªã«ããã£ã¨ãã¹ããä»ä¸ããæ¹æ³
PHPã§ï¼æã®æ¸ãæ¨ã¦ã«è¿ãã©ã¤ãã©ãªãæ¸ãå ´åãdebug_backtrace()é¢æ°ã使ã£ã¦åä¸ãã¡ã¤ã«å
ã«ãã¹ã*5ãè¨è¿°ãããã¨ããæ¹æ³ãã¨ãæ¹ã¯å¤ãã®ã§ã¯ãªããã¨æãã¾ãã*6
<?php namespace Hoge; class Foo { public function load($file) { return file_get_contents($file); } } if (debug_backtrace()) return; // test code. $foo = new Foo; var_dump($foo->load('http://www.example.com/')); // ãã¹ããªã®ã«www.example.comã«ã¢ã¯ã»ã¹ãã¦ãã¾ãï¼ï¼ãªãã¨ããããï¼
ãã®ãããªå ´åã«ããã¹ãã®ã¨ãã ãé¢æ°ããªã¼ãã¼ã©ã¤ããããã¨æã£ã¦debug_backtrace()ã®è¡ããå¾æ¹ã«æ°ããé¢æ°ãå®ç¾©ããã¨ãã¦ããé¢æ°ã®ãã¼ãã¯èªã¿è¾¼ã¿æã«è¡ããã¦ãã¾ããããé常å©ç¨ã®å ´åã«ã¾ã§åçç¡ç¨ã§ãªã¼ãã¼ã©ã¤ãããã¦ãã¾ãã¾ãã
<?php namespace Hoge; class Foo { public function load($file) { return file_get_contents($file); } } if (debug_backtrace()) return; $foo = new Foo; var_dump($foo->load('http://www.example.com/')); // ããã§å®ç¾©ãã¦ããæå³ã¨åãã¦ãã¹ãæ以å¤ããªã¼ãã¼ã©ã¤ããã¦ãã¾ãã function file_get_contents($name) { return 'this is test result!!'; }
ããã¯æã¾ããçµæã§ã¯ããã¾ããããã¹ãå®è¡æã®ã¿ãªã¼ãã¼ã©ã¤ãããã«ã¯ãã©ãããã°ããã§ããããã
ã¹ã³ã¼ããåºåã
ãããå®ç¾ããããã«ã¯ãé¢æ°å®ç¾©é¨åã®ã¹ã³ã¼ããåãã¾ãã
ãªã¼ãã¼ã©ã¤ãããé¢æ°ã®å®ç¾©é¨åã ããããã¯ã§å²ãã§ãã¾ããã¨ã§ãé¢æ°å®ç¾©ãå®è¡æã«è©ä¾¡ããããã¨ã«ãªãããã¹ãã¨ãã¦å®è¡ããå ´åã®ã¿ãªã¼ãã¼ã©ã¤ããããã¨ãã§ãã¾ãã
<?php namespace Hoge; class Foo { public function load($file) { return file_get_contents($file); } } if (debug_backtrace()) return; { // ããã§ããã¹ãæã®ã¿é¢æ°å®ç¾©ãæå¹ã«ãªãã function file_get_contents($name) { return 'this is test result!!'; } } $foo = new Foo; var_dump($foo->load('http://www.example.com/')); // this is test result!! ã¨ããçµæãããã£ã¦ããã
ããã¯ç¹å¥ãªå½ä»¤ããã¦ãã訳ã§ã¯ãªãããããã¯ã§ããåºåãã¦ããã°ã©ããªæ¹æ³ã§ããã¾ãã¾ããã
ç¡åé¢æ°ã«é¢æ°å®ç¾©ãéãè¾¼ãã
ãããã¯ã§åºåã£ã¦ãã¾ãå ´åã«ãç¹ã«å人çã«ãããããªã®ã¯ãç¡åé¢æ°ã«éãè¾¼ããè¨è¿°æ¹æ³ã§ãã
ãã®æ¹æ³ã®å©ç¹ã¯ãç¡åé¢æ°ã®å®è¡é¨åãã³ã¡ã³ãã¢ã¦ãããã ãã§ãªã¼ãã¼ã©ã¤ããããã©ãããåãæ¿ããããã®ã§ãå®ãªã½ã¼ã¹ã«ã¢ã¯ã»ã¹ããå ´å/ããªãå ´åã®ãã¹ããæå
ã§æ軽ã«åãæ¿ãã§ããã¨ããã§ãã
<?php namespace Hoge; class Foo { public function load($file) { return file_get_contents($file); } } if (debug_backtrace()) return; $override = function() { function file_get_contents($name) { return 'this is test result!!'; } }; $override(); // ãããã³ã¡ã³ãã¢ã¦ãããã¨ããªã¼ãã¼ã©ã¤ããã/ããªããåãæ¿ããããã $foo = new Foo; var_dump($foo->load('http://www.example.com/'));
è足
ã¡ãªã¿ã«ããããããã¯ã§åºåããã¨ãã件ã§èº«ããµãããªã話ããã¦ãã¾ãã¨ãå®ã¯if(!debug_backtrace()) { ... } ã¨å
¨ä½ãããã£ã¦ããã°æåããåé¡ã¯ãªãã®ã§ãã
ãããã®ããã«ãã¹ãã³ã¼ãå
¨ä½ãï¼æ®µãã¹ãããã®ã¯ãã£ãæªãã®ã§ãå®ç¾©é¨åã ããå²ãæ¹ãããã£ã½ãã¦ããããªããªãã¦æã£ã¦ã¾ãã
ã±ã¼ã¹ï¼ï¼ ããã³ã¨ãããã¹ãã«çµã¿è¾¼ãæ¹æ³
ãã¦ãã¾ãã¯ããã£ã¨æ¸ãå ´åã«ã¤ãã¦ç´¹ä»ãã¾ããããä¸ã®ä¸ã®å¤§åã®ãã¹ãã¯PHPUnitçã使ã£ã¦ãã¹ããã¡ã¤ã«ç¾¤ãä½ã£ã¦æ¸ããã®ã大å¢ãå ãã¦ãã¾ãã
ä»äºã§æ¸ãããªãã¦ãã¨ã«ãªã£ãå ´åãããã§ãããã
ãã¡ãã¨ãããã¹ãã¨ãã¦å®è¡ããå ´åãä¸è¨ã®ãããªï¼ãã¡ã¤ã«å
ã§ã®ããªãã¯ã¯ä½¿ãã¾ããã
ã§ã¯ã©ãããã°ããã®ãï¼
åå空éã®å¤éå®ç¾©
ãã®ãããªå ´åã«ã¯ãåå空éã®å¤éå®ç¾©ãå©ç¨ã§ãã¾ãã
åå空éã®å¤éå®ç¾©ã¨ã¯ãåä¸ã®åå空éãè¤æ°ã®ãã¡ã¤ã«ã«åå²ãã¦ãå¥ã
ã®å ´æã§å®ç¾©ãããã¨ã§ãã*7
<?php // fileA.php namespace Hoge; class Foo { public function load($file) { return file_get_contents($file); } } ?> ========== <?php // fileB.php namespace Hoge; class Bar { // ... } // å®ç¾©ãããã¡ã¤ã«ã¯éãããFooãBarãHogeåå空éã«å±ããã
ä¸è¨ã®ããã«ãè¤æ°ã®ãã¡ã¤ã«ã§åä¸åã®åå空éãè¤æ°å®ç¾©ã§ããä»æ§ãæ´»ç¨ãããã¨ã§ããã¹ãå®è¡æã®ã¿ãã¤ãã£ãé¢æ°ããªã¼ãã¼ã©ã¤ããããã¨ãã§ããããã«ãªãã¾ãã
å ·ä½çã«ã¯ãã©ã¤ãã©ãªå´ã®åå空éã¨ããªãåå空éããã¹ããã¡ã¤ã«å´ã«ãç¨æãããã¡ãå´ã§æ°ãã«ãªã¼ãã¼ã©ã¤ããããé¢æ°ãå®ç¾©ãããã¨ã§ããã¹ããã¡ã¤ã«ãå®è¡ããå ´åã ãé¢æ°ããªã¼ãã¼ã©ã¤ãã§ãã¾ãã
<?php // Lib.php namespace Hoge; class Foo { public function load($file) { return file_get_contents($file); } } ?> ========== <?php // TestCase.php namespace Test\Hoge; require_once 'Lib.php'; use Hoge; $foo = new Foo; var_dump($foo->load('http://www.example.com/')); // ãªã¼ãã¼ã©ã¤ããããçµæãããã£ã¦ããï¼ var_dump(file_get_contents('http://www.example.com/')); // www.example.comã«ã¨ãã«ãã namespace Hoge; // useã®å¾ã«æ¸ãã¦ãã£ã¦ãåé¡ãªãã function file_get_contents($name) { return 'this is test result!!'; } var_dump(file_get_contents('http://www.example.com/')); // ãªã¼ãã¼ã©ã¤ããããçµæãããã£ã¦ããï¼
ãã®ããã«æ¸ãã¨ãã©ã¤ãã©ãªåä½ã§å©ç¨ããã¦ããã¨ãã«ã¯æ®éã«å©ç¨ãããã¨ãã§ãããã¹ãå®è¡æã®ã¿file_get_contents()ããªã¼ãã¼ã©ã¤ãããã¾ãã
ããã«ããªã¼ãã¼ã©ã¤ãã®å®ç¾©é¨åãå¥ãã¡ã¤ã«ã¨ãã¦æ±ãããã¹ãã®åå¿
è¦ã«å¿ãã¦çµã¿è¾¼ããã¨ãã使ãæ¹ãå¯è½ã§ãã
<?php // Lib.php namespace Hoge; class Foo { public function load($file) { return file_get_contents($file); } } ?> ========== <?php // Override.php namespace Hoge; function file_get_contents($name) { return 'this is test result!!'; } ?> ========== <?php //TestCase.php namespace Test\Hoge; require_once 'Lib.php'; require_once 'Override.php'; use Hoge; $foo = new Foo; var_dump($foo->load('http://www.example.com/')); // ãªã¼ãã¼ã©ã¤ããããçµæãããã£ã¦ããï¼ var_dump(file_get_contents('http://www.example.com/')); // www.example.comã«ã¨ãã«ãã
å ãã¦ã以ä¸ã®ããã«ã©ããã³ã°ããå½¢ã§å©ç¨ããæ¹æ³ãããå¾ã¾ãã
<?php // Lib.php namespace Hoge; class Foo { public function load($file) { return file_get_contents($file); } } ?> ========== <?php // TestWrapper.php namespace Hoge; require_once 'Lib.php'; function file_get_contents($name) { return 'this is test result!!'; } ?> ========== <?php //TestCase.php namespace Test\Hoge; require_once 'TestWrapper.php'; use Hoge; $foo = new Foo; var_dump($foo->load('http://www.example.com/')); // ãªã¼ãã¼ã©ã¤ããããçµæãããã£ã¦ããï¼ var_dump(file_get_contents('http://www.example.com/')); // www.example.comã«ã¨ãã«ãã
ã©ã®æ¹æ³ãããè¯ããã¯ãç¶æ³ã«åããã¦ï¼ä»å¾ã®ãã¦ãã¦ã®ç©ã¿éãã«ãã£ã¦ããã¹ããã©ã¯ãã£ã¹ãè¦ãã¦ããã ããã¨æãã¾ãã
ããã
ãã®ããã«namespaceãæ´»ç¨ãããã¨ã§ãããã¾ã§ãå¤é¨ãªã½ã¼ã¹ãç°å¢ã«ã«ä¾åããããå¾ãªãã£ãé¨åã®ãã¹ããç°å¢ããåãé¢ãããã¨ãã§ããããã«ãªãã¾ãã
ãã¡ãããå®è£ ã®ä»æ¹æ¬¡ç¬¬ã§ã¯å¿ ãããåãé¢ãããã¿ã¼ã³ã°ããã§ã¯ãªã*8ã¨æãã¾ãããããããæ¢åã®é¢æ°ãæ¸ãæãã¦ã¾ã§ãã£ãããããã¹ããæ¸ããã¨ããçãããªãããã£ã¨æ¥µåããã¹ãã§ããå½¢ãã§å®è£ ã試ã¿ãã¯ãã ã¨æã*9ã®ã§ãå¿é ã¯ãªãã¯ãã§ãã
ãã¦ãã¦ããããªè¨³ã§å¤§å¤é·ããªã£ã¦ãã¾ãã¾ããããã·ã¹ãã ã«ä¾åããªããã¹ããæ¸ãã¦ãå¿å®ãããªæ¥ã ããéãããã ããã
Happy Testing Life!!
*1:æä½ã§ãããã¨æããã©ãã£ã¡ãã¡ã¤ã³ã ã£ããããããã
*2:ãã¨ãã°ã対象ã¨ãªããã¤ãã£ãé¢æ°ã®å¼ã³åºãé¨åã ããªãã¸ã§ã¯ãåãã¦ãã¢ãã¯ã¨å·®ãæ¿ããããªã©ã
*3:runkitãè¦æ±ãããã¹ããªãã¦è¦ããã¨ãæ¸ãããã¨ãªããã©ãï¼ã§ãããï¼ã£ã¦ã ãã§ãã
*4:ãªããæ¬è¨äºã§ããã¤ãã£ãé¢æ°ã®ãªã¼ãã¼ã©ã¤ããã¨å¼ãã§ããã®ã¯ãåå空éã®ä¸ã§ãã¤ãã£ãé¢æ°ã¨ååã®é¢æ°ãå®ç¾©ã»å©ç¨ãããã¨ãæãã¾ããæ¬å½ã«ã°ãã¼ãã«ç©ºéã®é¢æ°ããªã¼ãã¼ã©ã¤ãã§ãã訳ã§ã¯ãªãã®ã§ããããããã
*5:ãã¹ãã¨ãã¨ãã¬ãµã³ãã«ã½ã¼ã¹ã§ãããã¨ãã»ã¨ãã©ã§ããããã
*6:Pythonã®__name__ == "__main__"ã¨ä¼¼ããããªãã®ã§ã該å½ã®ãã¡ã¤ã«ãç´æ¥å®è¡ãããå ´åã«ã¯debug_backtrace()ä¸é¨ã®ãã¹ãã³ã¼ããèªã¿è¾¼ã¾ããå¤é¨ããincludeçã§èªã¿è¾¼ã¾ããå ´åã«ã¯ã該å½è¡ä»¥éã®ã³ã¼ããå®è¡ãããªããªãã¾ãã
*7:å¤éå®ç¾©ã¨ããå¼ã³æ¹ãæ£ãããã¯ãããã¾ãããæ確ãªç¨èªãå®ç¾©ããã¦ããªãæ°ããã¾ãã
*8:ãã¨ãã°ãfile_get_contents()ã使ã£ã¦HTTPãªã½ã¼ã¹ãåãã«ããå¦çãå®è£ ããã¨ãã«ãHTTPã®ã¬ã¹ãã³ã¹ãããåå¾ã$http_response_headerãã¼ã«ã«å¤æ°ããåå¾ããããã«ãã¦ãããããªå ´åã«ã¯ããªã¼ãã¼ã©ã¤ãããé¢æ°ã使ã£ã¦ãæ£ããå¦ççµæãå¾ãããªãã§ãããã
*9:å ã®ä¾ã§è¨ãã°ããã¼ã«ã«å¤æ°ã®ä»£ããã«stream_get_meta_data()é¢æ°ã使ã£ã¦åå¾ããå½¢ã§å®è£ ããããªã©ã