這個(gè)測(cè)試使用了 PEAR 提供的 HTTP Client 模塊。我發(fā)現(xiàn)它比內(nèi)嵌的 PHP Client URL Library(CURL)更簡(jiǎn)單一點(diǎn)兒,不過(guò)也可以使用后者。
有一個(gè)測(cè)試會(huì)檢查所返回的頁(yè)面,并判斷這個(gè)頁(yè)面是否包含 HTML。第二個(gè)測(cè)試會(huì)通過(guò)將值放到請(qǐng)求的 URL 中來(lái)請(qǐng)求計(jì)算 10 和 20 的和,然后檢查返回的頁(yè)面中的結(jié)果。
這個(gè)頁(yè)面的代碼如下所示。
清單 11. TestPage.php
<html><body><form>
<input type="text" name="a" value="<?php echo($_REQUEST['a']); ?>" /> +
<input type="text" name="b" value="<?php echo($_REQUEST['b']); ?>" /> =
<span id="result"><?php echo($_REQUEST['a']+$_REQUEST['b']); ?></span>
<br/>
<input type="submit" value="Add" />
</form></body></html>
這個(gè)頁(yè)面相當(dāng)簡(jiǎn)單。兩個(gè)輸入域顯示了請(qǐng)求中提供的當(dāng)前值。結(jié)果 span 顯示了這兩個(gè)值的和。<span>標(biāo)記標(biāo)出了所有區(qū)別:它對(duì)于用戶(hù)來(lái)說(shuō)是不可見(jiàn)的,但是對(duì)于單元測(cè)試來(lái)說(shuō)卻是可見(jiàn)的。因此單元測(cè)試并不需要復(fù)雜的邏輯來(lái)找到這個(gè)值。相反,它會(huì)檢索一個(gè)特定<span>標(biāo)記的值。這樣當(dāng)界面發(fā)生變化時(shí),只要 span 存在,測(cè)試可以通過(guò)。
與前面一樣,首先編寫(xiě)測(cè)試用例,然后創(chuàng)建一個(gè)失敗版本的頁(yè)面。我們對(duì)失敗情況進(jìn)行測(cè)試,然后修改頁(yè)面的內(nèi)容使其可以工作。結(jié)果如下:
清單 12. 測(cè)試失敗情況,然后修改頁(yè)面
% phpunit TestPage.php
PHPUnit 2.2.1 by Sebastian Bergmann.
..
Time: 0.25711488723755
OK (2 tests)
%
這兩個(gè)測(cè)試都可以通過(guò),這意味著測(cè)試代碼可以正常工作。
在對(duì)這段代碼運(yùn)行測(cè)試時(shí),所有的測(cè)試都可以沒(méi)有問(wèn)題地運(yùn)行,這樣我們可以知道自己的代碼可以正確工作了。
不過(guò)對(duì) HTML 前端的測(cè)試有一個(gè)缺陷:JavaScript。超文本傳輸協(xié)議(HTTP)客戶(hù)機(jī)代碼對(duì)頁(yè)面進(jìn)行檢索,但是卻沒(méi)有執(zhí)行 JavaScript。因此如果我們?cè)?JavaScript. 中有很多代碼,必須創(chuàng)建用戶(hù)代理級(jí)的單元測(cè)試。我發(fā)現(xiàn)實(shí)現(xiàn)這種功能的佳方法是使用 Microsoft® Internet Explorer® 內(nèi)嵌的自動(dòng)化層功能。通過(guò)使用 PHP 編寫(xiě)的 Microsoft Windows® 腳本,可以使用組件對(duì)象模型(COM)接口來(lái)控制 Internet Explorer,讓它在頁(yè)面之間進(jìn)行導(dǎo)航,然后使用文檔對(duì)象模型(DOM)方法在執(zhí)行特定用戶(hù)操作之后查找頁(yè)面中的元素。
這是我了解的對(duì)前端 JavaScript. 代碼進(jìn)行單元測(cè)試的惟一一種方法。我承認(rèn)它并不容易編寫(xiě)和維護(hù),這些測(cè)試即使在對(duì)頁(yè)面稍微進(jìn)行改動(dòng)時(shí)也很容易遭到破壞。
編寫(xiě)哪些測(cè)試以及如何編寫(xiě)這些測(cè)試
在編寫(xiě)測(cè)試時(shí),我喜歡覆蓋以下情況:
所有正面測(cè)試
這組測(cè)試可以確保所有的東西都如我們期望的一樣工作。
所有負(fù)面測(cè)試
逐一使用這些測(cè)試,從而確保每個(gè)失效或異常情況都被測(cè)試到了。
正面序列測(cè)試
這組測(cè)試可以確保按照正確順序的調(diào)用可以像我們期望的一樣工作。
負(fù)面序列測(cè)試
這組測(cè)試可以確保當(dāng)不按正確順序進(jìn)行調(diào)用時(shí)會(huì)失敗。
負(fù)載測(cè)試
在適當(dāng)情況下,可以執(zhí)行一小組測(cè)試來(lái)確定這些測(cè)試的性能在我們期望的范圍之內(nèi)。例如,2,000 次調(diào)用應(yīng)該在 2 秒之內(nèi)完成。
資源測(cè)試
這些測(cè)試確保應(yīng)用編程接口(API)可以正確地分配并釋放資源 —— 例如,連續(xù)幾次調(diào)用打開(kāi)、寫(xiě)入以及關(guān)閉基于文件的 API,從而確保沒(méi)有文件依然是被打開(kāi)的。
回調(diào)測(cè)試
對(duì)于具有回調(diào)方法的 API 來(lái)說(shuō),這些測(cè)試可以確保如果沒(méi)有定義回調(diào)函數(shù),代碼可以正常運(yùn)行。另外,這些測(cè)試還可以確保在定義了回調(diào)函數(shù)但是這些回調(diào)函數(shù)操作有誤或產(chǎn)生異常時(shí),代碼依然可以正常運(yùn)行。