nightwatch.js 目前還不支援 Data Driven Testing
整個場景是要針對已知的數筆資料(可能會增減)對網站系統進行登入及查驗的動作,這些資料被塞在一個 .txt 檔內,理想狀況是 nightwatch.js 打開該檔後依序跑指定的 test case。但是它沒有迴圈的概念,所以永遠只跑第一筆記錄...
Google 後有人說可以用它的 mocha runner,但是... 看不懂啊... XD
沒關係,macOS 環境下有 shell,在外面跑迴圈把資料餵食給 nightwatch.js 總行了吧?
奇怪的命令列參數傳遞
待測試的資料是數字型的,直接丟給 nightwatch.js 竟然報錯...node_modules/nightwatch/bin/nightwatch tests/crawler.js 1234345678
The "path" argument must be of type string. Received type number
at validateString (internal/validators.js:125:11)
at Object.resolve (path.js:1080:7)
最後傳參數的方式變成以下這種很奇怪的格式:node_modules/nightwatch/bin/nightwatch tests/crawler.js -ABCDEFG -12345678
在 nightwatch.js 內取得參數的方式倒是不難,就是濾掉 - 號以及檔案內可能參雜的 \r 或 \n 而以。const args = process.argv.slice(3);
const param1 = args[0].replace( /^-/, '').replace( /\r/, '').replace( /\n/, '');
const param2 = args[1].replace( /^-/, '' ).replace( /\r/, '').replace( /\n/, '');
點選某一個 radiobutton
本來應該使用 .click() api 去點選頁面上的元件,但它馬的不會動啊... 最後透過 .execute() 搭配 document.querySelector() 方式總算點到了... = =browser
.execute(function(){
document.querySelector( '#A > span > input[type="radio"]' ).click();
document.querySelector( '#B > div.section_wrap > form > ul > li.ht > div.ipt_wrap_2 > label:nth-child(1) > span > input[type="radio"]' ).click();
})
checkbox 還要檢查是不是可見元素
一樣還是透過 .execute() 及 document.querySelector() 取得 checkbox 本身,然後檢查它的 offsetParent 屬性是不是 null,若是 null 表示使用者看不到該 checkbox ,可以不用理它。另外,別忘了檢查 checked 屬性,亂點可是會捅漏子的...
let box = document.querySelector( '#A input[type="checkbox"]' );
if( box.offsetParent != null && box.checked == false ) {
box.click();
}
關於 elements() API
如果單純在 elements() 的 callback() 檢視它的傳回值時,會看到一組類似這樣的東西:
{ sessionId: '31bf7adb53f4f9a93a0c4404e41d303f',
status: 0,
value:
[ { ELEMENT: '0.7637505561737095-2' },
{ ELEMENT: '0.7637505561737095-3' },
{ ELEMENT: '0.7637505561737095-4' } ] }
這似乎是 Selenium 內部用來管理 element 用的代號,可以透過 .elementIdXXXXXX() 之類的 API 取得真正的 element 的指定屬性(對,是那個指定屬性放在 .value 屬性內,不是傳回該 element ),所以可以這樣子捉出頁面上的資訊:browser
.elements( 'css selector', 'div.plan_items', function(result){
result.value.forEach(element => {
browser.elementIdAttribute(element.ELEMENT, 'id', function(result){
console.log( result.value );
planList.push( result.value.replace( /^plan_items_/, '' ) );
});
});
})
結論
這些心得微小的不足為外人道,但它馬的花了我 2 天啊....補個幹!