2013-02-27 133 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的字符串中(然後從來沒有使用過)!沒有什麼實際上當你準確地看到代碼時,令人驚訝,但是當你的思想模糊不清時,通過假設你的正確代碼的複製粘貼不可能出錯!

相關問題