以Selenium IDE建立測試案例:無限捲頁
無限捲頁是我近日在「布丁布丁吃什麼?」新增的功能。當使用者瀏覽到網頁末端時,他不需要點選「較舊的文章」連結換下一頁,無限捲頁功能就會自動載入下一頁的內容。
現在我要撰寫一個測試案例(Test Case),檢查無限捲頁功能是否能夠正確地運作。
測試目的
- 將瀏覽範圍移到畫面尾端,觸發無限捲動功能,然後確定文章數量有比之前更多。
測試指令大綱
無限捲頁測試指令編號清單
功能 | 測試指令編號 |
B. 無限捲頁功能 | |
1. 讀取網頁 | B1-1 B1-2 B1-3 |
2. 觸發無限捲頁 | B2-1 B2-2 B2-3 |
無限捲頁測試指令清單
測試指令編號及測試目的 | 初始狀態 | 操作 | 預期輸出資料或結果 |
B1-1 開啟首頁 | 使用者在瀏覽器中開啟首頁網址 | 瀏覽器開啟首頁網址 | 首頁正確載入,JavaScript皆有正確初始化 |
B1-2 確認讀取前文章數量 | 接B1-1 | 計算css:.post-outer的個數,存入變數postOuterBefore | 變數值低於5 |
B1-3 顯示讀取前文章數量 | 接B1-2 | 在記錄中顯示postOuterBefore的值 | 變數值低於5 |
B2-1 捲動頁面到最下方,觸發無限捲頁功能 | 接B1-3 | 網頁捲軸往下移動到畫面末端 | 觸發無限捲頁功能 |
B2-2 確認無限捲頁功能開始讀取 | 接B2-1 | 確認無限捲頁讀取訊息顯示 | 無限捲頁正常顯示讀取訊息 |
B2-3 確認無限捲頁功能正常讀取完畢 | 接B2-2 | 等待無限捲頁讀取訊息隱藏 | 讀取訊息隱藏,下一頁文章已經載入 |
B3-1 確認讀取後文章數量 | 接B2-3 | 計算css:.post-outer的個數,存入變數postOuterAfter | 變數值低於10 |
B3-2 顯示讀取後文章數量 | 接B3-1 | 在記錄中顯示postOuterAfter的值 | 變數值低於10 |
B3-3 確認讀取後文章數量大於讀取前文章數量 | 接B3-2 | 確認postOuterAfter大於postOuterBefore | true |
建立測試指令
這次的測試指令需要用到Selenium的元素計算與變數儲存,也不是單純用錄製(Record)功能就能完成。
詳細的指令內容,請參考Selenium的指令說明。在前一篇「以Selenium IDE建立測試案例:圖片延緩載入」中介紹過的指令,這邊就只會簡略敘述而已。
設定等待時間
- Commend: setTimeout
- Target: 60000
- Value:
由於「布丁布丁吃什麼?」的首頁開啟速度非常慢。為了避免open指令在開啟網頁的過程中因為讀取太久而發生錯誤,所以測試案例正式開始之前,先將逾時限制時間設定為60秒。
B1-1 開啟首頁
- Commend: open
- Target: http://pulipuli.blogspot.com/
- Value:
接著使用open指令開啟「布丁布丁吃什麼?」的首頁。開啟之後的網頁畫面如下:
B1-2 確認讀取前文章數量
待首頁開啟完畢之後,接下來就是要計算進行無限捲動讀取前的文章數量。Blogger版面中,文章會放在class為post-outer的元素中。而在這個指令中,我想要把讀取前的文章數量存放入postOuterBefore變數中。
既要計算元素的數量,也要存入變數,就要使用Selenium的storeXpathCount指令:
- Command: storeXpathCount
- Target: //*[@class="post-outer"]
- Value: postOuterBefore
storeXpathCount(xpath, variableName)
參數:
- xpath - XPath表示式。不需要用XPath的count()函式,Selenium會自動產生。
回傳:
指定XPath符合的元素數量。
這似乎是目前為止第一次用到Value欄位的指令。storeXpathCount會需要兩個參數:第一個參數是XPath表示式,寫在Target欄位中;第二個參數是變數名稱,寫在Value欄位中。
值得一提的是,第一個參數只能用XPath表示式,而不能用平常習慣的CSS選擇器。不過XPath倒也沒這麼難學,我比較一下這兩者的差別。
- CSS選擇器:css=.post-outer
- XPath表示式:xpath=//*[@class=”post-outer”]
相信聰明的你應該能夠輕易地從CSS選擇器轉換到XPath表示式吧。
storeXpathCount指令不會發生任何錯誤,執行完畢之後就會直接執行下一個指令。
B1-3 顯示讀取前文章數量
- Command: echo
- Target: postOuterBefore的數量:${postOuterBefore}篇文章
- Value:
為了確認storeXpathCount計算時讀取前文章的數量到底正不正確,在此以echo指令來輸出postOuterBefore變數。你可以注意到postOuterBefore變數在Selenium的指令中是以「${變數名稱}」的方式使用。你也可以在JavaScript中讀取Selenium的變數,用法是「storedVars[ “變數名稱]” ] 」,這在下面指令中也會用到。
echo會在Log欄位中顯示訊息,預期的訊息將會是:
[info] echo: postOuterBefore的數量:7篇文章
由於首頁的文章數量可能會變動,所以數值也會隨之改變。在此只要先記錄讀取前的文章數量即可,以方便進行比較。
B2-1 捲動頁面到最下方
- Command: runScript
- Target: window.scrollTo(0, $("#footer-wrapper").offset().top);
- Value:
接下來執行一段JavaScript程式,讓頁面捲動到頁尾的位置。$(“#footer-wrapper”)是Blogger的頁尾區塊,如下圖:
B2-2 確認無限捲頁功能開始讀取
如果無限捲頁有正常執行,那麼此時應該會顯示讀取中的訊息,並有一個小型的動畫圖片,如下圖:
這個讀取中的訊息會包含在id為infscr-loading的元素中,所以在此要先等待這個元素顯示,使用waitForVisible指令。
- Command: waitForVisible
- Target: css=#infscr-loading
- Value
waitForVisible(locator)
參數:
- locator - 元素定位器
回傳
如果該元素呈現可見狀態(visible),則回傳true;否則回傳false。
- locator - 元素定位器
這邊使用了waitForVisible,而不是用waitForElementPresent,這兩者的差別在於前者特別指定該元素的狀態是「可見的」,而後者只要該元素存在這頁面中,不管是顯示或隱藏,都會回傳true。
在這邊我們要確定讀取訊息的顯示,所以是用waitForVisible,而不是用waitForElementPresent。
B2-3 確認無限捲頁功能正常讀取完畢
當無限捲頁順利讀取完之後,讀取訊息會隱藏起來。在此用waitForNotVisible來確認無限捲頁讀取訊息是否有正確地隱藏。
- Command: waitForNotVisible
- Target: css=#infscr-loading
- Value:
waitForNotVisible剛好跟waitForVisible相反。當無限捲頁順利讀取完成之後,這個指令就會回傳true,然後進入下一個指令。
B3-1 確認讀取後文章數量
經過無限捲頁讀取下一頁的文章之後,在此再用storeXpathCount來記錄讀取後文章的數量,並存到變數postOuterAfter中。
- Command: storeXpathCount
- Target: //*[@class="post-outer"]
- Value: postOuterAfter
B3-2 顯示讀取後文章數量
跟之前顯示讀取前文章數量一樣地,現在也用echo顯示一下postOuterAfter的結果吧。
- Command: echo
- Target: postOuterAfter的數量:${postOuterAfter}篇文章
- Value:
B3-3 確認讀取後文章數量大於讀取前文章數量
如果無限捲動真的讀取了下一頁的文章,那麼變數postOuterAfter應該要大於變數postOuterBefore才對。在Selenium的指令中,可以利用JavaScript語法來撰寫表示式,並用assertExpression指令來檢查該表示式的結果是否符合預期:
- Command: assertExpression
- Target: javascript{storedVars['postOuterAfter'] > storedVars['postOuterBefore']}
- Value: true
assertExpression(expression, pattern)
參數:
- expression - 一段表示式,它將會回傳一個值。
- pattern - 預期比對的值
回傳:
expression符合pattern,則回傳true;否則回傳false。
assertExpression特別適合用來檢查JavaScript執行結果是否正確,不過在此我是用JavaScript來檢查Selenium的變數值。如果要用JavaScript表示式,那麼語法將會是「javascript{程式}」。在JavaScript中取得Selenium變數的方法則是使用「storedVars[“變數名稱"]」。
在assertExpression中的expression參數不使用JavaScript表示式的話,expression通常會被視為字串來處理,而pattern也就是字串比對的模式了。
如果無限捲頁有順利運作,postOuterAfter應該要大於postOuterBefore,而測試也會順利通過。
測試案例結束訊息
在測試案例結束時加上一個訊息,表示測試已經結束。
- Commend: echo
- Target: 無限捲頁測試完成
- Value:
幫測試案例加上註解
最後在測試案例中寫些註解,讓人更容易理解測試的內容與目的。這樣子無限捲頁測試案例就大功告成了。
測試運作結果
在Selenium IDE中按下「Play current test case」按鈕,就能夠執行目前選擇的測試案例,用以檢查剛剛建立的各種測試指令是否有如預期地運作。
檔案下載
運作影片
結語
總算是寫完了。其實我還想要繼續研究一下Selenium Remote Control伺服器的架設,不過似乎沒有這麼多時間來摸索。所以這次就先學著寫測試案例,以後有機會再繼續研究吧。