無論何時,你隻要編寫一行新的代碼,你就有可能引入新的Bug。你應該使用自動測試,該教程将向你顯示如何為你的應用程式編寫單元測試和功能測試。
Symfony2測試很大程式上依賴PHPUnit,它的最佳實踐,和一些約定。這部分并不是PHPUnit本身的文檔,但如果你還是不能了解的話,你可以閱讀它優秀的文檔 。
Symfony2使用PHPUnit 3.5.11或以上版本。
預設的PHPUnit配置将在你Bundle的Tests/子目錄中查找測試:
對指定應用程式運作測試套件是簡單的:
代碼的覆寫範圍可以通過 --coverate-html 來生成。
編寫Symfony2單元測試與标準PHPUnit的單元測試沒什麼不同。通常推薦将Bundle目錄結構複制到Tests/子目錄中。是以為Acme\HelloBundle\Model\Article類所寫的測試會放置在Acme/HelloBundle/Tests/Model/ArticleTest.php檔案中。
在單元測試中,自動加載通過src/autoload.php檔案是自動啟用的(這在phpunit.xml.dist檔案中是被預設配置的)。
為指定檔案或目錄運作測試也十分容易:
功能測試檢查應用程式不同層的內建(從路由到視圖)。就PHPUnit關注度而言,它們與單元測試沒什麼不同,除了它們有一個非常特殊的工作流:
*制作一個請求
*測試響應
*點選連結或送出表單
*修正和重複
請求、點選和送出通過一個知道如何與應用程式通信用戶端來實作。要通路該用戶端,你的測試必須繼承Symfony2的WebTestCase類。沙箱提供了一個HelloControoler控制器簡單的功能測試,如下所示:
createClient()方法傳回一個與目前應用程式綁定的用戶端
request()方法傳回一個Crawler對象,該對象可以用于在Response中選擇元素。可以用來點選連結,也可以用來送出表單。
當Response的内容是XML或HTML文檔,可以隻使用Crawler對象。對于内容的其它類型,可以通過$client->getResponse()->getContent()來得到内容。
點選連結:首先選擇Crawler使用XPath表達式或CSS選擇器的連結,然後用Client去點選它:
送出表單也非常簡單;選擇一個表單按鈕,你可以覆寫一些表單的值,然後送出相應的表單:
每個表單項根據它的類型都有相對應的方法:
如果不想一次改變一個表單項,你也可以發送一個數組給submit()方法:
現在你可以很輕易浏覽應用程式,使用聲明去測試看看程式實際上是否按你所預期的執行。使用Crawler在DOM上執行中斷:
或者,如果你隻是想聲明内容包含一些文本,test可以直接針對Response内容。如果Response不是一個XML/HTML文檔,則無法實作。(這段翻得不暢,留下英文原文吧)
Or, test against the Response content directly if you just want to assert that the content contains some text, or if the Response is not an XML/HTML document:
在一段時間之後,你會注意到你總是寫同一類型的聲明。為了你更快地開始,這裡有一個常用的聲明清單:
測試用戶端模拟類似浏覽器的HTTP用戶端。
測試用戶端基于BrowserKit和Crawler元件。
用戶端知道如何制作一個發往Symfony2應用的請求:
request()方法将HTTP方法和URL作為參數,然後傳回一個Crawler實體。
使用Crawler去發現Response中的DOM元素。這些元素随後可以用于點選連結和送出表單:
click()和submit()方法都傳回一個Crawler對象。這些方法浏覽應用程式并隐藏大量細節的最好方式。例如,當你送出一個表單時,它自動比對HTTP方法和表單URL、它給你一個設計良好的API去上傳檔案、它合并表單預設值和送出值,等等儲如此類。
在接下來的Crawler章節中,你将學到更多關于Link和Form對象。
但你也可以使用request()方法的附加參數來模拟表單送出和複雜請求:
當一個請求傳回一個重定向響應,用戶端會自動遵循它。這個行為可以被followRedirects()方法改變:
當用戶端遵循響應進行重定向時,你可以使用followRedirect()迫強使它進行重定向:
最後但并非不重要,當在同一腳本使用多個用戶端工作時,你可以迫使每個請求都在它自己的PHP程序中執行以避免産生副作用。
用戶端支援許多實際浏覽器的操作
如果你使用用戶端去測試你的應用程式,你也許想去通路用戶端的内部對象:
你也可以得到最後請求相應的對象:
如果你的請求沒有被隔離,你也可以通路Container和Kernel:
強烈建議功能測試隻測試Response。但在幾種非常罕見的情況下,你也許想要通路一些内部對象對編寫聲明。在這種情況下,你可以通路依賴注入容器:
警告:如果你隔離了用戶端或使用HTTP層,它将不能工作。
如果你所需資訊被分析器檢出是可用的話,那麼用它們代替。
要讓聲明資料被分析器收集,你可以所下所示得到分析器:
預設狀态下,用戶端遵循HTTP重定向。但如果你想在重定向之前得到Response并将其重定向給自己,那麼調用followRedirects()方法:
每次你用Client生成請求時都會傳回一個Crawler執行個體。它允許你周遊HTML文檔、選擇節點、找到連結和表單。
當你用Client生成請求時,一個Crawler執行個體将會自動為你建立。但你也可以很容易地自行建立:
構造函數有兩個參數:第2個參數是為連結和表單生成絕對URL的URL;第1個參數可以使用以下内容:
* HTML文檔
* XML文檔
* DOMDocument執行個體
* DOMNodeList執行個體
* 上述元素的數組
建立之後,你可以添加更多的節點:
方法
描述
addHTMLDocument()
HTML文檔
addXMLDocument()
XML文檔
addDOMDocument()
DOMDocument執行個體
addDOMNodeList()
DOMNodeList執行個體
addDOMNode()
DOMNode執行個體
addNodes()
上述元素的數組
add()
接受上述任一進制素
象jQuery一樣,Crawler有方法去周遊HTML/XML文檔的DOM:
filter('h1')
比對CSS選擇器的節點
filterXpath('h1')
比對XPath表達式的節點
eq(1)
指定索引的節點
first()
第1個節點
last()
最後1個節點
siblings()
兄弟節點
nextAll()
所有後面的兄弟節點
previousAll()
所有前面的兄弟節點
parents()
父節點
children()
子節點
reduce($lambda)
所有被調用後不傳回false的節點
你可以通過鍊式方法調用來疊代縮小你選擇的節點,注意你每個比對節點用的方法都需要傳回一個新的Crawler執行個體。
使用count()函數得到儲存在Crawler:count($crawler)中的節點數。
Crawler可以從節點提取資訊:
你可以選擇帶有周遊方法的連結,但selectLink()快捷方法更為友善:
它選擇包含指定文本的連結,或者alt屬性包含指定文本的可點選圖檔。
Client對象的click()方法驅動一個被link()方法傳回的Link執行個體:
links()方法為所有節點傳回一個Link對象的數組。
你選擇有着selectButton()方法的表單:
注意我們選擇了表單按鈕而不是表單,因為表單可以有幾個按鈕;如果你使用周遊API,那麼注意你必須發現按鈕。
selectButton()方法可以選擇按鈕标簽并送出input标簽;這兒有一些發現它們的技巧:
* 值,屬性的值
* 圖檔的id或alt屬性
* 按鈕标簽的id或name屬性
當你有一個代表按鈕的節點,調用form()方法去得到一個Form執行個體,因為表單包含按鈕節點:
當調用form()方法時,你也可以發送一個覆寫預設值的那些表單項值的數組:
如果你想為表單模拟一個特定的HTTP方法,将其作為第2個參數:
Client可以送出一個Form執行個體:
表單項的值也可以作為submit()方法的第2個參數發送:
更複雜的情況,使用Form執行個體,并用一個數組來設定每個單獨表單項的值:
也有設計良好的API按照表單項的類型去操作它的值:
你可以通過調用getValues()方法得到将送出的值。被上傳的檔案也可以通過getFiles()傳回的數組中得到。getPhpValues()和getPhpFiles()也傳回被送出的值,但是以PHP格式傳回的(它将方括号中的關鍵詞轉換成PHP數組)。
每個應用程式都有它自己的PHPUnit配置,它們被儲存在phpunit.xml.dist檔案中。你可以編輯這個檔案以改變預設值或者建立phpnit.xml檔案去為你的本地機調整配置。
在你的代碼庫中儲存phpunit.xml.dist檔案,并忽略phpunit.xml檔案。
預設情況下,測試隻被儲存在那些通過運作phpunit指令的“标準”Bundle中,(标準是指測試位于Vendor\*Bundle\Tests名稱空間)。但你可以很友善地添加更多的名稱空間。例如,下面的配置将測試添加在安裝的第三方Bundle中。
為了包含代碼範圍中的其它名稱空間,也可以編輯<filter>段:
通過功能測試使用的Client建立一個在特定測試環境下運作的Kernel,是以你可以如你所願地調整它:
你也可以改變預設環境(test),通過覆寫調試模式(true),并将其做為選項發送給createClient()方法:
如果你的應用程式是根據一些HTTP頭來運作的話,那麼将它們作為第2個參數發送給createClient():
你也可以覆寫每個請求的HTTP頭。
覆寫test.client.class參數或定義一個test.client服務來提供你自己的Client。
本文轉自 firehare 51CTO部落格,原文連結:http://blog.51cto.com/firehare/586500,如需轉載請自行聯系原作者