我正在使用一个重构工具,该工具可以生成php文件。这些生成的文件也可以包含变量,函数和类。
我想编写单元测试,以测试那些文件是否按预期工作,但是我不知道该怎么做。
如果我要求使用if (! @require('my_new_file.php') ) {
的文件不正确,我仍然会遇到解析错误,无法捕获。
我在函数内调用require
,但是所需文件中的定义在函数外仍然可用。我该如何避免呢?是否可能需要在范围内的文件,因此它不会污染全局名称空间?
即使我在函数内调用eval(file_get_contents('my_new_file.php'))
,在my_new_file.php
中定义的函数也是全局可用的。
答案 0 :(得分:1)
为生成的文件生成PHPunit测试;例如。与PhpUnitGen:
composer install paulthebaud/phpunit-generator
当这些是CLI脚本时,请始终使用exit(0)
和exit(1)
。
答案 1 :(得分:0)
函数和类始终在周围的名称空间中定义,因为它是语言功能,所以不会对其进行任何更改。您可以将一个名称空间注入到生成的文件中,以防止它们污染其他名称空间,这将使名称冲突成为一个问题。
除此之外,您可以通过流程将测试代码与测试代码隔离。一种方法是pcntl_fork()
(如果可用),或者exec()
作为中等替代。测试框架可能会提供另一种方法(我相信PHPUnit就是这样!),以便清除或保护全局名称空间。
答案 2 :(得分:0)
如果我了解您要做什么,我会使用:
$output = exec("php script_to_test.php");
然后检查输出是否为所需的输出。 exec方法在一个单独的过程中执行您的php脚本,并以字符串形式返回输出。从那里,您应该能够获得测试所需的结论。您还可以解析输出并搜索通知,警告,致命错误等...
答案 3 :(得分:0)
正如其他人所建议的那样,听起来像在单独的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;
}