最近更新: 2008-04-21

A patch of isEditable of Selenium Core 0.83

日前配合 Selenium 撰寫一個 Web 應用軟體的測試案例,案例中有一句斷言要判定指定的表單輸入欄位是唯讀的 (readonly)。我個人很直覺地使用了 assetrNotEditable,但測試結果卻是錯的。後來我又試了 assertEditableassertAttributeassertNotAttribute 等寫法。始終無法正確而一致地判定輸入欄位的唯讀屬性 (readonly)。

依據參考文件 (Selenium IDE Reference) ,assertEditable/assertNotEditable 的說明,這兩種斷言都是調用 isEditable() 判斷。於是我開啟 selemium-api.js 後搜尋 isEditable ,找出它的源碼內容。結果發現它只判斷輸入控制元件 (input element) 的 disabled 屬性,而未判斷 readonly 屬性。

基本上,disabledreadonly 對使用者而言,同樣都令輸入控制元件不能修改內容。兩者的差別主要在於,一個具 disabled 屬性的輸入控制元件,其值不會被遞交回伺服器;而 readonly 屬性的輸入控制元件,其值可能會被遞交回伺服器 (在 W3C HTML Specification 中,這句話的意義等同 "視瀏覽器實作而定")。如下例所示:

<form action="test.php">
    <input id="i1" name="i1" value="1" disabled="disabled" />
    <input id="i2" name="i2" value="2" readonly="readonly" />
    <input id="i3" name="i3" value="3" />
</form>

<?php
echo '<pre>';
print_r($_POST);
echo '</pre>';
?>

因為 i1 具有 disabled 屬性,其值不會被遞交。而i2 僅具有 readonly 屬性,雖然使用者不能修改欄位內容,但其值仍會被遞交。故 test.php 受理後只會收到 i2,i3 兩個輸入控制元件的值。如下所示:

Array
(
    [i2] => 2
    [i3] => 3
)

對使用者而言,這些細節是他們感受不到的。按理說,assertEditable/assertNotEditable 應該會同時判斷輸入控制元件的 disabledreadonly 這兩個屬性。可惜 Selenium Core 並不這麼做。雖然不知道原因,不過開發中的案子已經在不少地方使用 readonly (主要是用於資料欄位的"檢視"動作),於是我選擇修改 Selenium Core 的 isEditable 內容。

如果開發團隊習慣使用 readonly 令輸入控制元件之值不可被修改,則 Selenium Core 預設的 assertEditable/assertNotEditable 將造成撰寫測試案例的困擾。可以透過修改或自定 isEditable 動作的方式,加入 readonly 屬性的判斷動作。

selenium-api.js
Selenium.prototype.isEditable = function(locator) {
    /**
   * Determines whether the specified input element is editable, ie hasn't been disabled.
   * This method will fail if the specified element isn't an input element.
   *
   * @param locator an <a href="#locators">element locator</a>
   * @return boolean true if the input element is editable, false otherwise
   */
    var element = this.browserbot.findElement(locator);
    if (element.value == undefined) {
        Assert.fail("Element " + locator + " is not an input.");
    }
    //return !element.disabled;

    return (!element.disabled && !element.getAttribute('readonly'));
};

Firefox 2.x 版不支援 element.readonly 的寫法,要用 W3C DOM 正式的寫法 element.getAttribute('readonly') 才可以。

Selenium IDE 的使用者,可以用 "Option/Selenium Core extensions",以自定測試動作的方式覆蓋掉原先的 isEditable 內容。或者,用 zip 解壓工具,打開 selenium-ide-0.8.7.xpi ,再打開其中的 "chrome/selenium-ide.jar",修改 "/content/selenium/scripts/selenium-api.js" 的內容。改好後再用 zip 壓縮工具包回去。(.xpi/.jar 其實都是 zip 壓縮檔)

樂多舊網址: http://blog.roodo.com/rocksaying/archives/5895631.html