. /** * PHPUnit autoloader for Moodle. * * @package core * @category phpunit * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** * Class phpunit_autoloader. * * Please notice that phpunit testcases obey frankenstyle naming rules, * that is full component prefix + _testcase postfix. The files are expected * in tests directory inside each component. There are some extra tests * directories which require both classname and file path. * * Examples: * * vendor/bin/phpunit core_component_testcase * vendor/bin/phpunit lib/tests/component_test.php * vendor/bin/phpunit core_component_testcase lib/tests/component_test.php * * @package core * @category phpunit * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class phpunit_autoloader implements PHPUnit_Runner_TestSuiteLoader { public function load($suiteClassName, $suiteClassFile = '') { // Let's guess what user entered on the commandline... if ($suiteClassFile) { // This means they either entered the class+path or path only. if (strpos($suiteClassName, '/') !== false) { // Class names can not contain slashes, // user entered only path without testcase class name. return $this->guess_class_from_path($suiteClassFile); } if (strpos($suiteClassName, '\\') !== false and strpos($suiteClassFile, $suiteClassName.'.php') !== false) { // This must be backslashed windows path. return $this->guess_class_from_path($suiteClassFile); } } if (class_exists($suiteClassName, false)) { $class = new ReflectionClass($suiteClassName); return $class; } if ($suiteClassFile) { PHPUnit_Util_Fileloader::checkAndLoad($suiteClassFile); if (class_exists($suiteClassName, false)) { $class = new ReflectionClass($suiteClassName); return $class; } throw new PHPUnit_Framework_Exception( sprintf("Class '%s' could not be found in '%s'.", $suiteClassName, $suiteClassFile) ); } /* * Try standard testcase naming rules based on frankenstyle component: * 1/ test classes should use standard frankenstyle class names plus suffix "_testcase" * 2/ test classes should be stored in files with suffix "_test" */ $parts = explode('_', $suiteClassName); $suffix = end($parts); $component = ''; if ($suffix === 'testcase') { unset($parts[key($parts)]); while($parts) { if (!$component) { $component = array_shift($parts); } else { $component = $component . '_' . array_shift($parts); } if ($fulldir = core_component::get_component_directory($component)) { $testfile = implode('_', $parts); $fullpath = "{$fulldir}/tests/{$testfile}_test.php"; if (is_readable($fullpath)) { include_once($fullpath); if (class_exists($suiteClassName, false)) { $class = new ReflectionClass($suiteClassName); return $class; } } } } } throw new PHPUnit_Framework_Exception( sprintf("Class '%s' could not be found in '%s'.", $suiteClassName, $suiteClassFile) ); } protected function guess_class_from_path($file) { // Somebody is using just the file name, we need to look inside the file and guess the testcase // class name. Let's throw fatal error if there are more testcases in one file. PHPUnit_Util_Class::collectStart(); PHPUnit_Util_Fileloader::checkAndLoad($file); $includePathFilename = stream_resolve_include_path($file); $loadedClasses = PHPUnit_Util_Class::collectEnd(); $candidates = array(); foreach ($loadedClasses as $loadedClass) { $class = new ReflectionClass($loadedClass); if ($class->isSubclassOf('PHPUnit_Framework_TestCase') and !$class->isAbstract()) { if (realpath($includePathFilename) === realpath($class->getFileName())) { $candidates[] = $loadedClass; } } } if (count($candidates) == 0) { throw new PHPUnit_Framework_Exception( sprintf("File '%s' does not contain any test cases.", $file) ); } if (count($candidates) > 1) { throw new PHPUnit_Framework_Exception( sprintf("File '%s' contains multiple test cases: ".implode(', ', $candidates), $file) ); } $classname = reset($candidates); return new ReflectionClass($classname); } public function reload(ReflectionClass $aClass) { return $aClass; } }