Protractor 環境躍進篇 (4.0.10)

筆者與 Protractor 交往的時間也不算短, 算一算都快兩年了, 這些日子以來, Protractor 總是為筆者所撰寫出來的新前端功能掛上一層保障, 讓服務每次 release 後總能帶給所有 user 既可靠又完善的體驗

筆者在撰寫一系列 Protractor 文章時, 均是 based on version 1.8, 在完成既有程度的 testing script 撰寫後, 由於該版本已能滿足自身的測試需求, 再加上筆者由於作業系統 (Windows 7)的限制, 無法往上升級到 2.x 版 (當時的最新版本), 便如此一直延用該版到 2016/10

鎖版號的做法…真的 OK 嗎 ?

這個問題其實一直盤旋在筆者腦中, 畢竟 browser 更新的速度不同往昔, 我們都知道 protractor 主要是透過 webdriverJS 去驅動我們所撰寫的 test script, 也就是說有可能潛伏著 webdriverJS 驅動不了的窘境, 它宛若是顆未定時的炸彈, 讓筆者每次跑完 end to end testing 的時候總覺得是幸運的, 是撿到的

終於…在 Chrome Version 54 的推出後, 這顆炸彈終於引爆, 我們再也無法透過既有的指令來更新最新的 webdriverJS

webdriver-manager update

雖然說坊間有很多有趣的方法可以避開, 直接去更新它, 不過總的來說, 鎖版帶來的僅僅是一時的安逸, 該付出的技術債可是一點都少不了, 與其取巧投機, 到不如踏時正面迎戰.

於是乎~ 筆者便決定把自身既有的測試環境作一次大升級, 接下來便會以 node.js, protractor 以及 cucumber 三大主角作不同探討, 並把筆者自身所遭遇到的問題以及解法描述出來, 希望能夠對同樣有著鎖版夢饜的朋友們有所幫助

首先我們先看 node.js 的部分

node.js

node.js 的版本從原先的 0.x 版直接升到最新的 6.9.1, 由於它有向下兼容既有的 js 寫法, 所以倒也不必擔心需要整個翻新到 ES 2015 的語法, 升級 node 可以說是最無痛的一環

只要到 node 官網, 便可以看到根據不同 OS 所推出的安裝檔, 選擇合適的將其下載並安裝即可

node.js official download page

透過 command line 我們可以看到 node.js 當前的版本

node.js version 6.9.1

完成 node.js 的升級之後, 接下來便是 cucumber 的部分

cucumber.js

cucumber 版本的升級著實讓筆者有受驚的感覺, 想當初該 community 曾經釋出不再進行更新的聲明, 看了一下它的更新紀錄, 沒想到也默默的來到了 version 1.3.1, 那麼對於 cucumber 的部分, 我們該怎麼更新呢 ?

首先透過 command line 進行安裝

npm install -g cucumber

透過 command line 我們可以看到 cucumber.js 當前的版本

cucumber.js version 1.3.1

完成更新後, 與既有版本最大的差別便是在 hook 上面, 它 defult 會有一個 timeout 的設定為 5000 ms, 只要 testing script 的 function 跑出過該數值, 便會 throw error 出來無法繼續 run 下去, 因此, 我們最先要解決的就是該 timeout 的設定, 畢竟比較完整的 end to end testing function 要超過五秒是很稀疏平常的事情

我們來看一下 hook 該怎麼設定

var myHooks = function() {    this.setDefaultTimeout(600 * 1000);};module.exports = myHooks;

透過 setDefaultTimeout, 便可以設定我們希望的 timeout 數值, 其單位為 ms. 有興趣的朋友也可以點擊筆者分享的 github 觀看實際的 code 是怎麼撰寫的 (github)

接下來是最常被使用的 hook 莫過於當 step fail 發生時, 截取當前 browser 畫面的功能, 有圖有真相, 透過螢幕截圖, 可以幫助我們更快的去追蹤該錯誤出現的時機, 方便我們勾勒出整個輪廓

這類截圖的 hook 通常被掛在 StepResult 的 callback 中, 我們先來看一下既有的 hook 寫法

var stepResultHooks = function() {    this.StepResult(        function(event, callBack) {            var stepResult, step;                        stepResult = event.getPayloadItem('stepResult');            step = stepResult.getStep();
if (stepResult.isFailed()) { ................... ................... ................... }//end if } );};module.exports = stepResultHooks;

在 version 1.3.1 中 stepResult.isFailed 這個 method 已不復存, 也因此當錯誤發生時, 它並不會如預期的掉到我們所設定的 if 當中, 那麼…我們該如何改寫這個 hook 呢 ?

var stepResultHooks = function() {    this.StepResult(        function(event, callBack) {            var stepResult, step;                        stepResult = event.getPayloadItem('stepResult');            step = stepResult.getStep();
if (stepResult.getFailureException()) { ................... ................... ................... }//end if } );};module.exports = stepResultHooks;

如上所示, 只要把它 replace 成 getFailureException 即可, 只要錯誤發生, 我們便可以透過該 method 取得 true, 自然的就可以完成預設的處理程序了 (github)

最後, 要注意的是 cucumber output 的 information, 筆者先前有撰寫過 dragonKeeper.js, 透過 dragonKeeper 我們可以動態的將 scenario 組合起來, 變成一個 flow testing, dragonKeeper 的運作原理, 便是透過 command line 去動態 run cucumber, 再將 output 出來的 information 作一匯集整理, 不過同樣的 format (pretty) 在 1.3.1 中變得更加的豐富, 除了多出了 Warning 這個 section 外, 每一個 step 前面也會多了一個 “?” 的符號, 也就是說…我們的 parser 要做更多的加工, 才能產出我們預期的 format, 也因此如果有透過 run cucumber command line 並對其 output 加工的朋友們, 可能也要注意一下相關的 parser 喔!

dragonKeeper parser: https://github.com/meistudioli/auto...

以上便是筆者有關 cucumber 升級後所做的相關調整, 接下來便要進入重頭戲 Protroctor 囉!

protractor

再進行安裝前, 筆者很怕又會遇到先前 2.x 版裝不了的狀況, 一旦裝不了, 可以說整個就 GG 了, 於是便在忐忑不安的狀態下 key 入了下列的 command

npm install -g protractor

透過 command line 我們可以看到 protractor 當前的版本

protractor version 4.0.10

皇天不負苦心人, 筆者終於順利升級了 protractor 的版本了, 立馬透過下面的 command 來更新 webdriverJS 的版本

webdriver-manager update

更新完後, 觀看一下相關的版號

各 driver version

chrome driver version 已經順利更新到 2.25 了 (出問題不能更新的是 2.24), 到這裡, 我們已經完成了最基本的基礎建設了

像是這種直接跳大版號更新, 理論上都不會太順利, 說無縫移轉通常都是包著糖衣的毒藥, 設定變更或者是 method remove 都不會太意外, 接下來筆者會分享我們需要怎麼做才能讓 protractor 和 cucumber 能緊密的相互配合併完成我們所交付的 testing 吧!

Protractor 打從 version 3.0 以後, 便後 cucumber 作有效的切離了, cucumber 不再是其 default 的 framework 選項之一, 也因此, 我們再安裝完 cucumber 之後, 還要再安裝額外的 node module

npm install -g cucumbernpm install -g protractor-cucumber-framework

完成相關的 install 後, 接下來要看的便是 protractor.conf.js 中有關 cucumber 設定的部分

下面的範例為既有 protractor version 1.8 的設定

framework: 'cucumber',
cucumberOpts: { require: 'cucumber/**/*.js', tags: [ '@E2E', '~@X' ], format: 'summary'}

如上面所述, cucumber 以不再是 protractor 所認得的 framework, 所以在 3.0 以後的版本, 我們都需要透過下列的設定來做

framework: 'custom',frameworkPath: require.resolve('protractor-cucumber-framework'),
cucumberOpts: { require: 'cucumber/**/*.js', tags: [ '@E2E', '~@X' ], format: 'summary'}

透過 framework 和 frameworkPath 的設定, protractor 終於可以和 cucumber 再次建立啟羈絆 !!

以上便完成了 protractor 的安裝了, 跑一下先前所寫好的 test script, 不意外的, 筆者得到了若干 fail, 其中最吸睛的莫過於下列的 error log

E/launcher - $(...).then is not a functionE/launcher - TypeError: $(...).then is not a function    at C:WWWautomationfeaturesstepscommonStepDefinition.js:12:27    ........    ........    ........    at process._tickCallback (internal/process/next_tick.js:103:7)E/launcher - Process exited with error code 199

element finder return 的不再是 promise 的 format, 當初為了讓 testing 可以被有序的進行測試, 筆者用了很多 element finder 作起手式, 隨著 4.0.10 的到來, 看來勢必得做些更動了, 我們先來看一下既有的 test script

$('body').then(    function(element) {        element.getAttribute('className').then(            function(className) {                expect(className).to.be.equal('mei');            }        );    }).then(callback, callback);

上面的 code 主要先找到 document.body 這個 element, 接下來驗證它的 className 是否為 ‘mei’

為了讓起手式一樣可以 return promise 讓整體測試可以被接續起來, 我們可以使用既有的一些 method 來達到這樣的需求, 並完成我們的初衷, 在這裡, 筆者使用了 isPresent 這個 method 來達到這樣的需求, 所以上面的 test script 經過改寫後, 就會變成

var body;
body = $('body');
body.isPresent().then( function(flag) { body.getAttribute('className').then( function(className) { expect(className).to.be.equal('mei'); } ); }).then(callback, callback);

透過 isPresent 的呼叫, 它一樣可以 return promise 的格式出來, 整個 test script 只要小幅度的進行調整, 便可以快速的讓它在 protractor version 4.0.10 中活躍 ! 達到力與美最小成本的異動 !!

起手式修正之後, 在筆者的 test script 中幾乎都不用更動, 看來 4.0.10 保留了大部分既有的 method 呼叫方式, 這實在可喜可賀啊 !!

以下 video 截錄了完成環境升級後, 從 dragonKeeper 動態 generate testing flow 以及完整的將該 flow 進行 testing 的過程, 主要是以 Yahoo 奇摩 拍賣為主要測試對像, 歡迎點擊該連結進行一覽

dragonMultiSpec(Y! 拍賣): https://www.youtube.com/watch?v=bB-otyL6v-w

另外, 筆者有將相關的 testing script 放到 github 中, 歡迎有興趣的朋友點擊 reference 的網址進行一覽

以上, 便是整個環境升級的過程與經驗分享, 希望透過這樣的分享, 能讓所有皆受困於鎖版號窘境的朋友們可以大膽放手下去做, 如果對於文章中有任何不解或者是遭遇到困難之處, 也歡迎隨時隨地和筆者聊聊一同討論, 成長的路上, 你我相隨, 並不寂寞…

Reference:

轉載文章 – Protractor 環境躍進篇 (4.0.10)

mei

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *