測試 JavaScript


如 果頁面中包括JavaScript,使用HtmlUnit測試,基本上不用什麼改變,因為HtmlUnit就像個無畫面的瀏覽器,有JavaScript 的話也會自動執行,如果JavaScript會改變畫面,雖然沒有畫面,但畫面實質就是依DOM樹結構,所以要判斷畫面有無改變,就是判斷DOM樹結構或 各節點有無變化。

舉例來說,如果想測試 修改文件 中第二個範例,可以如下:
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3);
HtmlPage page = webClient.getPage(
  "https://openhome.cc/Gossip/JavaScript/samples/ModifyNodes-2.html");
       
page.getElementById("image").click();
assertEquals(
    page.getElementById("container2"),
    page.getElementById("image").getParentNode());

       
page.getElementById("image").click();
assertEquals(
    page.getElementById("container1"),
    page.getElementById("image").getParentNode());


打算測試Ajax也是可行的,例如想測試
建立非同步物件 中的範例,可以如下:
WebClient webClient = new WebClient();
HtmlPage page = webClient.getPage(
 "https://openhome.cc/Gossip/JavaScript/samples/XMLHttpRequest-1.html");
page.getElementById("req").click();
assertEquals(1, page.getElementsByTagName("table").size());

(在撰寫文件時的HtmlUnit 2.8中,指定WebClient的版本為Firefox時Ajax請求就會失敗!)

實際上,HtmlUnit預設會以同步處理方式來發出請求與接收回應,這是由WebClient預設的AjaxController來控制,所以上例的click()後,會等到伺服端有回應後才會執行下一行。WebClient會在真正發出Ajax請求前,呼叫AjaxControllerprocessSynchron()方法,這個方法的傳回值決定了最後要以同步(true)或非同步(false)發出請求,如果你想要在Ajax請求發出前作一些動作,或決定是否同步請求,則可以如下:
        webClient.setAjaxController(new AjaxController() {
            @Override
            public boolean processSynchron(HtmlPage page, WebRequest request,
                    boolean async) { // async 預設是傳入false
                // 作一些前置處理
                return false; // false 表示非同步處理
            }
        });

預設的AjaxController其實只作了以下:
public class AjaxController implements Serializable {
    ...
    public boolean processSynchron(final HtmlPage page,
                       final WebRequest request, final boolean async) {

        return !async;
    }
}

AjaxController直接與主執行緒同步,如果想與運行測試時的執行緒同步,而非主執行緒,則可以設定NicelyResynchronizingAjaxController。例如:
webClient.setAjaxController(new NicelyResynchronizingAjaxController());

如果頁面中的JavaScript有alert()函式,則可以註冊AlertHandler,例如使用CollectingAlertHandler實作:
CollectingAlertHandler alertHandler = new CollectingAlertHandler();
webClient.setAlertHandler(alertHandler);

在JavaScript執行時若執行了alert(),則會被CollectionAlertHandler收集,你可以使用getCollectedAlerts()以List<String>取得alert()的訊息。類似地,像confirm()、prompt()等,都有對應的setConfirmHandler()setPromptHandler()可以使用。

有關ActiveX的模擬,可以參考官方網站上 Use ActiveX 的說明。