6

我是 PHPUnit 测试框架的新手。

我们知道move_uploaded_file()PHP 的功能只有在通过 http POST 方法上传文件后才会起作用

所以,问题是如何在 PHP 命令行中模拟这个

注意:使用 selenium 我们可以模拟 webform .. 但我需要另一种选择。

4

5 回答 5

8

您基本上需要使您的代码更具可测试性。将其分解,以便您可以将通过 HTTP 上传文件的简单操作与其余代码分开进行测试。的主要用途move_uploaded_file是设置一个额外的安全停止,这样您就不会被欺骗移动其他文件,move_uploaded_file只需确保文件是在同一个请求中上传的,然后移动它。您也可以简单地使用移动文件rename。因此,将您的应用程序分解为一个Request对象来表示和封装当前的 HTTP 请求,包括使用is_uploaded_file. 验证后,您可以使用rename而不是move_uploaded_file. 在您的测试中,您可以模拟该Request对象并测试您的其他代码。

您也可以简单地制作可move_uploaded_file模拟的,例如:

class Foo {

    public function do() {
        ...
        $this->move_uploaded_file($from, $to);
        ...
    }

    protected function move_uploaded_file($from, $to) {
        return move_uploaded_file($from, $to);
    }

}

例如,在您的测试中,您可以扩展/模拟该类并覆盖Foo::move_uploaded_file为 always return true

于 2012-11-26T11:58:10.180 回答
3

这就是PHP 测试框架(PHPT) 的用武之地。它与 PEAR 一起安装,允许您通过编写文件并使用或.phpt执行它来将 HTTP 请求、I/O 操作、文件上传等提供给 PHP 脚本。您还可以使用PHPUnit 运行它们和。run-phptpear run-tests <file.phpt>PhptTestCasePhptTestSuite

要模拟文件上传,您需要使用与浏览器发送的相同数据的--POST_RAW--部分。这是来自 PHP QAT 站点的示例:

重要提示:不幸的是,他们网站上的示例没有任何解释就失败了。

is_uploaded_file.phpt

--TEST--
is_uploaded_file() function
--CREDITS--
Dave Kelsey <d_kelsey@uk.ibm.com>
--SKIPIF--
<?php if (php_sapi_name()=='cli') die('skip'); ?>
--POST_RAW--
Content-type: multipart/form-data, boundary=AaB03x

--AaB03x
content-disposition: form-data; name="field1"

Joe Blow
--AaB03x
content-disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain

abcdef123456789
--AaB03x--
--FILE--
<?php
// uploaded file
var_dump(is_uploaded_file($_FILES['pics']['tmp_name']));

// not an uploaded file
var_dump(is_uploaded_file($_FILES['pics']['name']));

// not an uploaded file
var_dump(is_uploaded_file('random_filename.txt'));

// not an uploaded file
var_dump(is_uploaded_file('__FILE__'));

// Error cases
var_dump(is_uploaded_file());
var_dump(is_uploaded_file('a', 'b'));

?>
--EXPECTF--
bool(true)
bool(false)
bool(false)
bool(false)

Warning: is_uploaded_file() expects exactly 1 parameter, 0 given in %s on line %d
NULL

Warning: is_uploaded_file() expects exactly 1 parameter, 2 given in %s on line %d
NULL

跑步

pear run-tests --cgi=PHPCGI is_uploaded_file.phpt

Manuel Pichler 在博客文章中写了一个例子,但它也失败了。

于 2012-11-26T20:58:35.773 回答
2

如果您想使用 PHPUnit 测试文件上传而不模拟实际move_uploaded_file检查,您可以使用.phptPHPUnit 可以执行的测试用例,因此模拟 Web 请求。

基本上,您创建一个.phpt如下所示的文件:

独立示例:uploadTest.phpt

--TEST--
Example test emulating a file upload
--POST_RAW--
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryfywL8UCjFtqUBTQn

------WebKitFormBoundaryfywL8UCjFtqUBTQn
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain

Qafoo provides quality assurance support and consulting

------WebKitFormBoundaryfywL8UCjFtqUBTQn
Content-Disposition: form-data; name="submit"

Upload
------WebKitFormBoundaryfywL8UCjFtqUBTQn--
--FILE--
<?php

var_dump(is_uploaded_file($_FILES['file']['tmp_name']));

?>
--EXPECT--
bool(true)

运行使用phpunit uploadTest.phpt


有关完整说明,请查看描述详细信息的博客文章:

http://qafoo.com/blog/013_testing_file_uploads_with_php.html

还:There is working sample code over at github


更详细的现实世界示例:

--TEST--
Example test emulating a file upload
--POST_RAW--
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryfywL8UCjFtqUBTQn

------WebKitFormBoundaryfywL8UCjFtqUBTQn
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain

Qafoo provides quality assurance support and consulting

------WebKitFormBoundaryfywL8UCjFtqUBTQn
Content-Disposition: form-data; name="submit"

Upload
------WebKitFormBoundaryfywL8UCjFtqUBTQn--
--FILE--
<?php
require __DIR__ . '/UploadExample.php';

$upload = new UploadExample('/tmp');
$upload->handle('file');

var_dump(file_exists('/tmp/example.txt'));
?>
--EXPECT--
bool(true)
于 2012-11-26T20:58:07.893 回答
1

就个人而言,我喜欢上面deceze给出的答案。

然而,另一种可能性是使用命名空间

代码在Github上。

于 2014-07-18T13:04:22.717 回答
0

您可以使用cURL从命令行上传文件:

curl --form input-name=@filename http://localhost/upload.php

input-name是通常使用的 HTML 中输入字段的名称filename,是要上传的文件的路径和名称 - 如果它们包含一些特殊字符,请记住将它们放在引号中或转义特殊字符。

但是,这显然仍然需要从网络服务器运行脚本,显然这不是您想要的,所以请参阅如何为 PHP 中的文件上传编写测试?有关使用 PHPUnit 测试文件上传的方法。

于 2012-11-26T11:45:53.650 回答