在 測試 JSP 中, 你對add.jsp獨立進行測試,假設現在整個應用程式已部署,你要針對add.jsp在實際與應用程式其它元件結合後,是否功能正常,你也許會打開瀏覽 器連接add.jsp,然後按下表單按鈕,看看是否回到add.jsp並有錯誤訊息,你也許輸入表單中其中一個欄位,看看回到add.jsp後,該表單欄 位值是否回填,你也許正確填寫每個欄位,發送看看是否新增資料成功。
由於你是測試實際應用程式部署之後,功能是否正常,你是在執行功能測試(Functional test),且由於你是針對應用程式的介面進行測試,而非元件實際的撰寫內容,所以你是在執行黑箱測試(Block box test)。
你不用親自打開瀏覽器,一一手動進行測試,你可以使用 HtmlUnit,它可以用來模擬瀏覽器,某些程度上,你可以將HtmlUnit看作是一個沒有畫面的瀏覽器,你可以使用程式撰寫瀏覽器上的操作過程,接下來就可以自動執行操作。例如:
package test.cc.openhome;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.After;
import org.junit.Test;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
public class AddJSPTest {
    private WebClient webClient;
    private HtmlPage page;
    
    @Before
    public void setUp() throws Exception {
        // WebClient 代表一個瀏覽器
        webClient = new WebClient();
        // 指定 URL 取得 HTML 結果
        page = webClient.getPage(
                "http://localhost:8080/BookmarkOnline/add.jsp");
    }
    
    @After
    public void tearDown() throws Exception {
        // 關閉所有瀏覽視窗
        webClient.closeAllWindows();
    }
    
    @Test
    public void testNoError() throws Exception {
        // 測試初次造訪頁面
        // 以標準 DOM API 取得頁面元素進行斷言
        assertEquals(0, page.getElementsByTagName("h1").size());
    }
    
    @Test
    public void testError() throws Exception {
        // 取得表單元素
        HtmlForm form = page.getForms().get(0);
        // 取得發送按鈕
        HtmlSubmitInput button = form.getInputByValue("送出");
        // 發送表單,取得回應頁面
        HtmlPage page2 = button.click();
        // 以標準 DOM API 取得頁面元素進行斷言
        assertEquals("新增書籤失敗", 
                page2.getElementsByTagName("h1")
                     .item(0).getFirstChild().getNodeValue());
    }
    
    @Test
    public void testParameters() throws Exception {
        // 測試欄位回填功能
        String title = "測試";
        HtmlForm form = page.getForms().get(0);
        // 取得輸入欄位
        HtmlTextInput textField = form.getInputByName("title");
        // 在欄位填值
        textField.setValueAttribute(title);
        HtmlSubmitInput button = form.getInputByValue("送出");
        
        HtmlPage page2 = button.click();
        assertEquals(title, 
                page2.getElementsByName("title")
                     .get(0).getAttribute("value"));
    }
    
    @Test
    public void testSubmitSuccess() throws Exception {
        HtmlForm form = page.getForms().get(0);
        form.getInputByName("url").setValueAttribute("http://test");
        form.getInputByName("title").setValueAttribute("測試");
        form.getSelectByName("category").getOption(1).setSelected(true);
        HtmlSubmitInput button = form.getInputByValue("送出");
        // 假設發送成功的回應頁面標題為"新增書籤功成功"
        HtmlPage page2 = button.click();
        assertEquals("新增書籤成功", page2.getTitleText());
    }
}
上面的例子說明了幾個模擬瀏覽器操作的方式,你也可以模擬Firefox或Internet Explorer特定版本。例如:
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3);
      
      在撰寫文件的此時,可模擬的瀏覽器有:
- Firefox 2:BrowserVersion.FIREFOX_2(不建議使用)
- Firefox 3:BrowserVersion.FIREFOX_3
- Firefox 3.6:BrowserVersion.FIREFOX_3_6
- Internet Explorer 6:BrowserVersion.INTERNET_EXPLORER_6
- Internet Explorer 7:BrowserVersion.INTERNET_EXPLORER_7
- Internet Explorer 8:BrowserVersion.INTERNET_EXPLORER_8
在Cactus 1.8之後,HtmlUnit可與Cactus結合,只要在Classpath中包括HtmlUnit的相關程式庫,在Cactus的endXXX()方法中,就可以使用com.gargoylesoftware.htmlunit.WebResponse來取代org.apache.cactus.WebResponse(Cactus 1.2後到1.7可以換用 HttpUnit 的com.meterware.httpunit.WebResponse)。
HtmlUnit的使用十分直覺,關於頁面元素的取得,或相關動作的模擬(例如滑鼠點選、鍵盤鍵入等),都可以使用DOM標準API。如果連外需要透過代理伺服器,則可以如下:
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3,
"http://proxyserver", port);
// 設定連接代理伺服器時的名稱、密碼
DefaultCredentialsProvider credentialsProvider =
(DefaultCredentialsProvider) webClient.getCredentialsProvider();
credentialsProvider.addProxyCredentials("username", "password");

