2013-02-27 122 views
0

我继承了一个Zend Framework的Web应用程序,它既不是面向对象的,也没有在很多方面写得很好,而且它没有测试。因此,尽管我欣赏单元测试的价值,并且会在添加或重写代码时编写它们,但代码覆盖的功能测试似乎是最佳开始。它也是理解应用程序如何工作的理想工具。这是Zend Framework 1.11,Matthew Weier O'Phinney指出Zend_Test只能在3.4以上的PHPUnit中工作。所以我安装了最新的3.4.15。我已经验证了我可以扩展Zend_Test_PHPUnit_ControllerTestCase并在控制器上进行单元测试。PHPUnit Selenium RC测试覆盖适用于GET,但不适用于POST请求?

对于通过硒的功能测试,我有一些麻烦让代码覆盖工作。实际上,我怀疑从Selenium服务器的工作方式获取覆盖率数据在技术上是否可行,但在Does PHPUnit_Selenium Code Coverage Work?Does PHPUnit_Selenium Code Coverage Work?的帮助下,我终于可以与我的应用程序一起工作。能够看到代码的哪些部分受到不同请求的影响非常棒!

但我现在看到的问题是处理POST请求的代码似乎没有得到报告。

例如在控制器我有代码contactAction方法是这样的:

$this->view->form = $form; 
if ($this->getRequest()->isPost()) { 
    if ($form->isValid($this->getRequest()->getPost())) { 
    $values = $form->getValues(); 

。这是一个联系我们形式。在Selenium测试中,我打开url,输入消息,单击提交按钮,然后等待页面加载。当我运行测试时,我可以看到在浏览器中发生了这种情况,并且接收到了由硒键入的消息的电子邮件,所以我确信表单是用有效数据发布的,并且后面两行确实执行了。但在报道报道中,前两行是绿色,后两行是橙色。

我仪表两个prepend.php和append.php脚本记录以下信息:

 "(File: " . __FILE__ . "): REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD'] . "\n" . 
    "REQUEST_URI: " . $_SERVER['REQUEST_URI'] . "\n" . 
    "_COOKIE['PHPUNIT_SELENIUM_TEST_ID']: '" . print_r(isset($_COOKIE['PHPUNIT_SELENIUM_TEST_ID']), 1) . "'\n" . 
    "_GET['PHPUNIT_SELENIUM_TEST_ID']: '" . print_r(isset($_GET['PHPUNIT_SELENIUM_TEST_ID']), 1) . "'\n" . 
    "_POST['PHPUNIT_SELENIUM_TEST_ID']: '" . print_r(isset($_POST['PHPUNIT_SELENIUM_TEST_ID']), 1) . "'\n" . 

一个奇怪的是,只有在前面加上剧本曾经被记录下来,从来没有追加剧本。我不知道为什么,但它似乎不影响覆盖率数据(至少对于GET请求)。我见过的唯一可以解释的是,如果Zend MVC应用程序以exit()结尾?那有意义吗?

这里记录的内容为与我们联系互动:

(File C:\xampp\htdocs\myapp\public\prepend.php): REQUEST_METHOD: GET 
REQUEST_URI: /index/contact 
_COOKIE['PHPUNIT_SELENIUM_TEST_ID']: '1' 
_GET['PHPUNIT_SELENIUM_TEST_ID']: '' 
_POST['PHPUNIT_SELENIUM_TEST_ID']: '' 
extension_loaded('xdebug'): '1' 

(File C:\xampp\htdocs\myapp\public\prepend.php): REQUEST_METHOD: GET 
REQUEST_URI: /index/contact 
_COOKIE['PHPUNIT_SELENIUM_TEST_ID']: '1' 
_GET['PHPUNIT_SELENIUM_TEST_ID']: '' 
_POST['PHPUNIT_SELENIUM_TEST_ID']: '' 
extension_loaded('xdebug'): '1' 

(File C:\xampp\htdocs\myapp\public\prepend.php): REQUEST_METHOD: POST 
REQUEST_URI: /index/contact 
_COOKIE['PHPUNIT_SELENIUM_TEST_ID']: '1' 
_GET['PHPUNIT_SELENIUM_TEST_ID']: '' 
_POST['PHPUNIT_SELENIUM_TEST_ID']: '' 
extension_loaded('xdebug'): '1' 

(File C:\xampp\htdocs\myapp\public\prepend.php): REQUEST_METHOD: GET 
REQUEST_URI: /default/index/contact 
_COOKIE['PHPUNIT_SELENIUM_TEST_ID']: '1' 
_GET['PHPUNIT_SELENIUM_TEST_ID']: '' 
_POST['PHPUNIT_SELENIUM_TEST_ID']: '' 
extension_loaded('xdebug'): '1' 

(File C:\xampp\htdocs\myapp\public\prepend.php): REQUEST_METHOD: GET 
REQUEST_URI: /default/index/contact 
_COOKIE['PHPUNIT_SELENIUM_TEST_ID']: '1' 
_GET['PHPUNIT_SELENIUM_TEST_ID']: '' 
_POST['PHPUNIT_SELENIUM_TEST_ID']: '' 
extension_loaded('xdebug'): '1' 

(File C:\xampp\htdocs\myapp\public\prepend.php): REQUEST_METHOD: GET 
REQUEST_URI: /phpunit_coverage.php?PHPUNIT_SELENIUM_TEST_ID=a85030b0bcdb0460bfb17a83a373d6b5 
_COOKIE['PHPUNIT_SELENIUM_TEST_ID']: '' 
_GET['PHPUNIT_SELENIUM_TEST_ID']: '1' 
_POST['PHPUNIT_SELENIUM_TEST_ID']: '' 
extension_loaded('xdebug'): '1' 

正如你所看到的,GET请求得到记录两次,POST只有一次。也许这与只有GET请求似乎被覆盖而POSTS不覆盖的事实有关?但我真的不知道这种行为在几个方面,我不知道该怎么做,以帮助弄清楚。

有人对我为什么没有获得POST请求的覆盖率有什么想法,或者下一步可能要跟踪它吗?

+0

我刚才输入了一个答案,将我的XDebug版本从2.1.0更新到2.1.2解决了这个问题。但是我删除了它,因为进一步的测试显示,代码显示的内容是测试环境中的变化:密码已更改,因此登录失败。因此,如果登录成功,它会重定向,并且不会覆盖POST请求。登录失败后,它显示POST的覆盖范围,并重新显示表单。 XDebug的版本没有什么区别。这是WinXP SP3,PHP 5.3.1。 – sootsnoot 2013-03-02 19:43:13

回答

0

在这个问题中,我推测也许如果Zend框架调用exit(),这可能解释为什么append.php脚本永远不会被记录。所以,我找遍了ZF库的整个源调用exit()的,并且只有三个发现:

library/Zend/Controller/Action/Helper/Redirector.php:  exit(); 
library/Zend/Oauth/Consumer.php:  exit(1); 
library/Zend/OpenId.php:   exit(); 

了。在这种情况下不使用OAuth或的OpenID。但正如我在评论中所指出的,POST请求代码在登录失败并且表单重新显示时显示覆盖,但是当它成功并且重定向到欢迎页面时发生。所以重定向器看起来就像要检查的地方。

重定向,在这个应用程序使用统一的行动程序的代码:

$this->_redirect("some-url"); 

,我从来没有研究它是如何工作或者它的任何选项,因为它从来就不是一个问题。但有可能导致覆盖问题,我读了它的文档并浏览了Zend源代码。我发现有一个简单的选项可以使重定向不会调用exit()。所以我改变了有问题的:

return $this->_redirect("some-url", array('exit'=>false)); 

而瞧,POST请求缺少的代码覆盖率出现了!

现在我想知道是否应该重写_redirect,以便它始终抑制退出调用,或者如果我只应该在测试环境中这样做。我猜想在重定向时立即终止脚本可能会节省生产中的一些周期。

所以主要的问题就解决了。但神秘的是,我放入append.php脚本的日志代码仍然不会产生任何输出 - prepend.php脚本始终会生成日志输出,但永远不会附加.php。这是由于append.php没有输出,所以我在ZF内部调用了exit()函数,但似乎还有其他一些原因导致输出没有生成。

我终于也想出了这一个。这仅仅是附加脚本中的一个错字。我无法相信它,因为我“知道”我添加到append.php中的日志代码与prepend.php中的代码完全相同,从prepend到append进行了复制粘贴。但显然我发现了副本上的选择,并错过了消息文本的最后一行。当我终于看到缺失的一行时,我的第一反应是“这不可能,我应该得到一个语法错误,而不是缺少输出。”这是代码,因为我预计它是:

$msg ="\n(File " . __FILE__ . "): REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD'] . "\n" . 
     "REQUEST_URI: " . $_SERVER['REQUEST_URI'] . "\n" . 
     "_COOKIE['PHPUNIT_SELENIUM_TEST_ID']: '" . print_r(isset($_COOKIE['PHPUNIT_SELENIUM_TEST_ID']), 1) . "'\n" . 
     "_GET['PHPUNIT_SELENIUM_TEST_ID']: '" . print_r(isset($_GET['PHPUNIT_SELENIUM_TEST_ID']), 1) . "'\n" . 
     "_POST['PHPUNIT_SELENIUM_TEST_ID']: '" . print_r(isset($_POST['PHPUNIT_SELENIUM_TEST_ID']), 1) . "'\n" . 
     "extension_loaded('xdebug'): '". print_r(extension_loaded('xdebug'), 1) . "'\n"; 
file_put_contents($GLOBALS['PHPUNIT_COVERAGE_DATA_DIRECTORY'] . "/msg.log", $msg, FILE_APPEND); 

但我不小心错过了最后一行赋值到$味精。所以当我意识到它丢失了,并且在调用file_put_contents()之前看到了悬挂的字符串连接操作符之后,起初我感到困惑的是我没有得到语法错误。但是,当然php很高兴用$ msg的旧值(prepend脚本中赋值)调用file_put_contents(),并将其结果(写入的字节数)附加到分配给$ msg的字符串中(然后从来没有使用过)!没有什么实际上当你准确地看到代码时,令人惊讶,但是当你的思想模糊不清时,通过假设你的正确代码的复制粘贴不可能出错!

相关问题