Вопрос:

Как можно проверить созданные файлы php?

php

212 просмотра

5 ответа

2569 Репутация автора

Я работаю над инструментом рефакторинга, который создает файлы php. Эти сгенерированные файлы могут содержать переменные, функции и классы тоже.

Я хотел бы написать модульные тесты, чтобы проверить, работают ли эти файлы, как ожидалось, но я понятия не имею, как мне это сделать.

Если мне требуется неверный файл с if (! @require('my_new_file.php') ) {, я все равно получаю ошибку разбора, которую я не могу отловить.

Я вызываю requireвнутри функции, но определения в необходимых файлах по-прежнему доступны за пределами моей функции. Как я мог избежать этого? Можно ли требовать файл в области видимости, чтобы он не загрязнял глобальное пространство имен?

Даже если я вызываю eval(file_get_contents('my_new_file.php'))функцию, определенные в my_new_file.phpней функции доступны глобально.

Автор: Iter Ator Источник Размещён: 02.08.2019 09:30

Ответы (5)


0 плюса

13319 Репутация автора

Функции и классы всегда определяются в окружающем пространстве имен, ничто не изменит этого, потому что это языковая функция. Вы можете внедрить пространство имен в сгенерированные файлы, чтобы они не загрязняли другие пространства имен, что уменьшит конфликты имен.

Кроме этого, вы можете изолировать тестируемый код от тестового кода с помощью процессов. Одним из способов является pcntl_fork(), если таковые имеются, или в exec()качестве посредственной замены. Ваш тестовый фреймворк может предоставить другой способ (я полагаю, что PHPUnit имеет нечто подобное!), Так что глобальное пространство имен либо очищается, либо защищается.

Автор: Ulrich Eckhardt Размещён: 03.08.2019 07:31

0 плюса

887 Репутация автора

Если я понимаю, что вы пытаетесь сделать, я бы использовал:

$output = exec("php script_to_test.php");

И затем проверьте, является ли выход желаемым. Метод exec выполняет ваш php-скрипт в отдельном процессе и возвращает вывод в виде строки. Оттуда вы сможете получить выводы, необходимые для ваших тестов. Вы также можете анализировать вывод и искать уведомления, предупреждения, фатальные ошибки и т. Д ...

Автор: François Huppé Размещён: 04.08.2019 02:19

-1 плюса

442 Репутация автора

Вы должны использовать passthruфункцию. Образец кода:

$out = passthru("php test.php");

После этого вы можете просто посмотреть на вывод функции. Разве это не то же самое, что execвы спрашиваете? Нет. Хотя execвозвращает только последнюю строку вывода, passthruвозвращает необработанный вывод. Да, возможно, потребуется немного больше разбора, но если ваш скрипт возвращает более 1 строки, execон просто не будет работать так, как ожидалось. Вы можете прочитать больше об этом здесь .

Автор: Martin Dimitrov Размещён: 05.08.2019 12:48

0 плюса

11658 Репутация автора

как и предполагали другие, похоже, что запуск файла в отдельном php-процессе близок к тому, что вы хотите. но вы должны использовать proc_open () вместо этого, чтобы вы могли проверять как stdout, так и stderr (другие ответы здесь позволяют только проверять STDOUT, который не очень полезен при обнаружении ошибок), если ошибка происходит, ошибка, скорее всего, будет печатается в stderr (по умолчанию PHP печатает ошибки в stderr, а не в stdout.). В конце этого поста приведена пользовательская версия shell_exec, которая позволяет вам контролировать как stdout, так и stderr по отдельности, и позволяет записывать данные в stdin, если вашему сценарию нужны данные stdin, с его помощью вы можете тестировать отдельные сценарии, такие как

$cmd=implode(" ",array(
    "php",
    escapeshellarg("path/to/my_new_file.php"),
    // if your script needs extra arguments, add them here
)); 
$stdin=""; // if your script needs stdin data, add it here
$ret=my_shell_exec($cmd,$stdin,$stdout,$stderr);

после этого все, что ваш скрипт поместил в stderr, теперь находится в переменной $ stderr, а все, что он напечатал в stdout, находится в переменной $ stdout, проверьте, содержит ли он то, что вы ожидали. если это не так, ваш скрипт, вероятно, каким-то образом потерпел неудачу, содержимое $ stderr / $ stdout, вероятно, сообщит вам, как он потерпел неудачу.

function my_shell_exec(string $cmd, string $stdin=null, string &$stdout=null, string &$stderr=null):int{
    //echo "executing \"{$cmd}\"...";
    // use a tmpfile in case stdout is so large that the pipe gets full before we read it, which would result in a deadlock.
    $stdout_handle=tmpfile(); 
    $stderr_handle=tmpfile();
    $descriptorspec = array(
        0 => array("pipe", "rb"),  // stdin is *inherited* by default, so even if $stdin is empty, we should create a stdin pipe just so we can close it.
        1 => $stdout_handle,
        2 => $stderr_handle, 
    );
    $proc=proc_open($cmd,$descriptorspec,$pipes);
    if(!$proc){
        throw \RuntimeException("proc_exec failed!");
    }
    if(!is_null($stdin) && strlen($stdin)>0){
        fwrite($pipes[0],$stdin);
    }
    fclose($pipes[0]);
    $ret=proc_close($proc);
    rewind($stdout_handle);// stream_get_contents can seek but it has let me down earlier, https://bugs.php.net/bug.php?id=76268
    rewind($stderr_handle);// 
    $stdout=stream_get_contents($stdout_handle);
    fclose($stdout_handle);
    $stderr=stream_get_contents($stderr_handle);
    fclose($stderr_handle);
    //echo "done!\n";
    return $ret;
}
Автор: hanshenrik Размещён: 06.08.2019 06:48

0 плюса

24246 Репутация автора

Просто сгенерируйте тесты PHPunit для сгенерированных файлов; например. с PhpUnitGen :

composer install paulthebaud/phpunit-generator
Автор: Martin Zeitler Размещён: 11.08.2019 08:52
Вопросы из категории :
32x32