#php #namespaces #constants
#php #пространства имен #константы
Вопрос:
Я работаю с пространствами имен и PHP 5.3 в своем проекте framework. У меня есть основной App
класс и Autoloader
класс. В App
классе я настроил несколько переменных среды:
public static function setupEnv()
{
$os = 'UNIX';
if (stristr(PHP_OS,'WIN'))
{
$os = 'WIN';
}
if (!defined('DIRECTORY_SEPARATOR'))
{
define('DIRECTORY_SEPARATOR',($os == 'UNIX') ? '/' : '\');
}
define('DS', DIRECTORY_SEPARATOR);
if (!defined('PATH_SEPARATOR'))
{
define('PATH_SEPARATOR', ($os == 'UNIX') ? ':' : ';');
}
define('PS', PATH_SEPARATOR);
if (!defined('APP_PATH'))
{
define('APP_PATH', dirname(dirname(__FILE__)));
define('AP', APP_PATH);
}
}
Константы определяются правильно, и DIRECTORY_SEPARATOR
и DS
, и если я повторяю их здесь, они работают просто отлично. Пространство имен для этого — FeatherApp . В Autoloader
классе я использую DS
константу, и она просто отлично работает. Autoloader
Класс находится в том же пространстве имен Feather App.
Я запускаю PHPUnit и создал этот тест — setupEnv()
вызывается в setUp()
функции PHPUnit:
public function testAutoloadFunction()
{
$this->assertEquals(
dirname(dirname(__FILE__)) . DS.'Components'.DS.'Collections'.DS.'Collection.php',
FeatherAppAutoloader::Autoload('\Feather\Components\Collections\Collection')
);
}
Это не проходит тест, хотя путь возвращается правильно. В нем говорится:
Use of undefined constant DS - assumed 'DS'
Итак, это большая предыстория, чтобы ответить на мой вопрос — почему это ошибка? Я подумал, хорошо, может быть, мне нужно ссылаться на FeatherAppDS, но это приводит к следующему:
PHP Fatal error: Undefined constant 'FeatherAppDS' in /web/Feather/Tests/AutoloaderTest.php
Я думал, что константы были определены в глобальной области, так что разве это не должно работать? Если нет, то как мне заставить это работать, чтобы PHPUnit был доволен? Если я помещаю use FeatherApp
вверху, он все равно завершается с той же assumed 'DS'
ошибкой.
Кто-нибудь может это объяснить? Документация по PHP пока бесполезна!
Комментарии:
1. Одно из ваших наблюдений, должно быть, неверно. Константы не были определены, поэтому
setupEnv()
метод и / илиApp
класс не были запущены до unittest .2. Если я попытаюсь выполнить эхо
DS
передsetupEnv()
командой, оно будет пустым / неопределенным. Если я повторяю его послеsetupEnv()
, оно определено. Это не константа, определенная в другом месте. Итак, тот факт, что модульный тест использует правильное значение дляDS
, я бы сказал иначе.3. Добавьте
assert('defined("DS")');
в этот метод unittest, чтобы узнать больше. И добавьтеprint "setupEnv"
в функцию инициализации для отладки.4. Интересно, я только что протестировал на рабочей станции Windows с помощью WAMP, и это работает… но на моей рабочей станции Linux это не удается. Я еще немного покопаюсь в этом сегодня вечером.
5. ХОРОШО — я понятия не имею, что я сделал, но сейчас это работает. Я думаю, проблема в том, что я не проверял
if (!defined('DS'))
, и когдаsetUp()
функция выполнялась в последующих тестах, это вызывало проблемы. Это мое лучшее предположение. Теперь код работает!
Ответ №1:
У меня была очень похожая проблема, и я запустил тесты со следующими шагами:
-
Маркировка тестов
@runInSeparateProcess
аннотацией -
Переопределение
run()
в тестовом классе следующим образом:публичная функция run(PHPUnit_Framework_TestResult $result = NULL) { $this->setPreserveGlobalState(false); возвращает parent::run($result); }
-
Ввод
require_once()
, который приводит к определению константы в тестовом файле, вsetUp()
:общедоступная функция setUp() { require_once DIR.’/SetUpEnv.php ‘; }
Возможно, это не идеальное решение, но оно, несомненно, лучше, чем отсутствие решения вообще.
Я вычеркнул фрагменты (или, может быть, все целиком) из других ответов на StackOverflow и / или в других местах, но прошло некоторое время, поэтому приношу извинения источникам, которые я здесь не цитирую.