前端工程師寫 Robot Framework,可以嗎?
07 Nov 2019起因
過去在寫 End-to-End Testing 我都是用 WebdriverIO 或 Nightwatch,直到今年 10 月才開始接觸 Robot Framework。會選擇 Robot Framework(後端為 Python)來寫測試的原因非常簡單,就是 follow 團隊先前的決定而已 XD
至於團隊為什麼要選它,原因有二
- 第一,在整合測試上,團隊期待的 RD 和 QA 的 working model 是由 RD 實作 keyword 或元件,而 QA 只要拼湊這些 keyword 或是元件就能成為 test case。
- 第二,我們家的 QA 有些不是很喜歡寫程式,Robot Framework 用 keyword 來撰寫,看起來就很口語化,很簡單,上手的門檻低;或是比較熟悉寫後端的程式,不是那麼喜歡 JavaScript,所以決定選用 python-based 的 Robot Framework。
因此,原先前端工程師所用的 WebdriverIO 就被捨棄,與後端統一使用 Robot Framework。
以下 JavaScript WebDriver 的例子以 Nightwatch 或 WebdriverIO 來輔以說明。
前端工程師可以寫 Robot Framework 嗎?
如果你是個前端工程師,正在找個 End-to-End Testing 的框架,你要選哪一個呢?WebdriverIO?Nightwatch?Robot Framework?若團隊傾向寫 Robot Framework,前端能寫嗎?以下有一些狀況也許是可以來好好評估或注意的。
寫關鍵字 vs 寫程式
Robot Framework 是利用「關鍵字」來寫 test case 的,每個關鍵字基本上就像是一句話,也就是說,每一個 test case 由一句或多句話組成,非常口語化。因此,對於不擅長寫程式的人來說,降低了進入與熟悉門檻;而對於喜歡看到程式碼的人來說,可能就會覺得太鬆散了,沒有 coding 的 feel。
如下是一個範例,用來在文字框輸入帳號 admin。做的事有…
- 打開瀏覽器並到特定網站
http://www.sample.com
。 - 使用
<body>
是否可見來確定畫面載入完成。 - 清除 userid 這個欄位的值。
- 在 userid 這個欄位輸入字串「admin」。
Robot Framework 的寫法如下。
Open Chrome Browser To http://www.sample.com
Wait Until Element Is Visible css:body
Clear Input Text css:#userid
Input Text css:#userid admin
除了使用 Robot Framework 官方提供的 API 之外,當然也利用關鍵字包裹一些功能,使其更抽象化、更易於使用。
Nightwatch 的寫法如下。
browser
.url('http://www.sample.com')
.waitForElementVisible('body')
.clearValue('#userid')
.setValue('#userid', 'admin'); // 輸入帳號「admin」
See?Robot Framework 就真的滿像日常講話的,而 Nightwatch 基本上就是前端工程師所熟悉的 JavaScript,較好上手,這就是寫我們前端工程師每天都在寫的程式碼而已。
乍看之下好像還可以接受?那麼…以下舉幾個簡單的例子來說明前端工程師到底有什麼煩惱,可以接受就歡迎跳坑喔 (o´・ω・)σ)Д
)
語法差異太大
後端語言(以下使用 Python)和 Robot Framework 的語法與其 API 對前端所熟悉的 JavaScript 差異很大 (╥﹏╥)
第一個例子來看 For Loop。
在 Robot Framework 是這樣寫的。
@{list} Create List abc edf
:FOR ${item}} IN @{list}
\ ...
而在 JavaScript 可用 for、forEach 等來實作。
雖然看起來完全可以理解,但身為前端的我就硬是要從這麼基本的語法開始學起 _(┐ ◟;゚ д ゚)ノ
第二個例子來看條件判斷。
在 Robot Framework 是這樣寫的。
Run Keyword If ...
... ELSE ...
在 JavaScript 是這樣寫的。
if (condition 為 true) {
// ...
} else {
// ...
}
其他還有空白分隔(關鍵字內用一個空白分隔,關鍵字與關鍵字之間用 4 個空白分隔)…等,雖然還是可以理解,但就是有那麼一點差距。
學習這些基礎語法應該 3 天內就可以上手,但就是要花些時間轉換腦袋。
無法跟前端共用資料結構或共用檔案
由於 Robot Framwork 是 Python-based 的,因此無法跟前端共用資料結構或共用檔案,js 物件必須要轉換成為 json 格式,導致必須維護兩份資料。
在 WebdriverIO 或 Nightwatch 是這樣寫的,直接使用 JavaScript 物件即可。
const list = [
{
title: 'Dashboard Overview',
menu: ['item 1', 'item 2', 'item 3'],
},
{
title: 'Adding Widgets to the Dashboard',
menu: ['item 4', 'item 5', 'item 6'],
},
{
title: 'Creating a Widget',
menu: ['item 7', 'item 8', 'item 9'],
},
];
在 Robot Framework 是這樣寫的,要轉 json 格式。
list = [
{
'title': 'Dashboard Overview',
'menu': ['item 1', 'item 2', 'item 3',],
},
{
'title': 'Adding Widgets to the Dashboard',
'menu': ['item 4', 'item 5', 'item 6',],
},
{
'title': 'Creating a Widget',
'menu': ['item 7', 'item 8', 'item 9',],
},
]
UI 操作相關的 API 不足
面對 Robot Framework 沒有提供的 API 但前端又必須用到的,我們都會用終極大魔王 ◥(ฅº₩ºฅ)◤
關鍵字 Execute JavaScript
在裡面直接包 JavaScript 程式碼或直接引入一個 js 檔案來實作,身為前端工程師的我在這當中就不斷跟自己說「其實還是在寫 JavaScript 嘛!只是外殼包了 Robot Framework 而已!」那…怎麼不寫 JavaScript 就好 XD
範例如下,若想將畫面 scroll 到特定位置,在 WebderiverIO 我們可直接使用 JavaScript 的 API 的 scrollTo 來做。
window.scrollTo(x, y);
Nightwatch 沒有這類行為,因為基本上會將元素捲到可視範圍內,當然也可手動使用 moveToElement()
將滑鼠移到這個元素上。
browser.moveToElement(elem);
若一定要是 scroll 這個動作,也可直接利用 Nightwatch 提供的 execute 執行 JavaScript 程式碼。
browser.execute('scrollTo(x, y)');
在 Robot Framework 是這樣寫的,我們先定義一個新的關鍵字「Scroll To Position」,然後包一些 JavaScript 來做捲到特定位置的動作。
Scroll To Position
[Arguments] ${position}
Execute Javascript return window.scrollTo(${position})
或直接引入一個 js 檔案。
Scroll To Position
[Arguments] ${position}
Execute Javascript ${CURDIR}/scroll.js
這個 scroll.js 會放一個 IIFE 來立刻執行。
return (function() {
window.scrollTo(position);
})();
然後在 test case 中使用這個關鍵字。
Scroll To Position 0,0
無法 Mock 資料
雖然說 End-to-End Testing 應該要用實際在機器上的資料,但生資料做測試這件事情是要靠後端的,靠別人有 dependency 總是不開心 XD 若用 WebdriverIO 或 Nightwatch 就可以做 mock request,只是這樣的測試就不夠真實…各有利弊。
總結
身為前端工程師,我在撰寫 Robot Framework 的時候,起初最常遇到的問題是對於 Python 或 Robot Framework 語法的不熟悉,畢竟 Nightwatch 或 WebdriverIO 的 API 都還是用 JavaScript,順手多了!後來雖然稍微熟悉了,但寫起來對 UI 的操作的 API 就是少一些,導致我們需要利用 Execute JavaScript
創建新的關鍵字並在裡面包 JavaScript,多此一舉又十分麻煩,不推不推!之後想到什麼或遇到什麼再來補補吧!