如何测试生成的php文件?

时间:2019-08-02 09:30:21

标签: php

我正在使用一个重构工具,该工具可以生成php文件。这些生成的文件也可以包含变量,函数和类。

我想编写单元测试,以测试那些文件是否按预期工作,但是我不知道该怎么做。

如果我要求使用if (! @require('my_new_file.php') ) {的文件不正确,我仍然会遇到解析错误,无法捕获。

我在函数内调用require,但是所需文件中的定义在函数外仍然可用。我该如何避免呢?是否可能需要在范围内的文件,因此它不会污染全局名称空间?

即使我在函数内调用eval(file_get_contents('my_new_file.php')),在my_new_file.php中定义的函数也是全局可用的。

4 个答案:

答案 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;
}