KKStream SQA Intern 心得分享 (Web automation test)

yysu
BlendVision
Published in
16 min readFeb 14, 2018

在KKStream實習了半年左右(2017.07–2018.02),分享一下半年下來的心得及想法,回想當初真的是很意外的緣分。

[前情提要]

這篇不會有太多的技術成分,主要是分享一下半年來學到的網頁自動化測試及心得,可能文章會有點長,我寫完自己也很感動...

文章內使用Ruby code代表用Ruby寫的舊自動化測試系統,Webdriver.io代表用webdriver.io開發的新自動化測試系統

[實習過程記錄]

半年來的紀錄圖

簡而言之我在這半年的實習中做了兩件事情,一件是維護前一位實習生Frank寫的自動化測試 (Ruby + Selenium) ,包含四個 browser (Chrome、Firefox、Safari、IE),第二件事是建置新的自動化測試 (Webdriver.io),目前涵蓋到兩個 browser (chrome , firefox)。

Ruby(total 76 commits)

Webdriver.io(total 99 commits)

[7–8月]懵懂成長期

剛開始進去先練習照著寫好的測試計畫書來做測試練習,主要測試的平台有 Web、Android、ios 三個大平台,但實際上我們的產品還有在 WebTV、AndroidTV、AppleTV 等等平台運作。等到比較熟悉產品的內容及運作方式之後就開始接觸了神秘的自動化測試,這也是我第一次接觸到Ruby語言與Selenium Grid這個工具,還好ruby跟python撰寫起來很類似不是太難上手,也因為不太有時間讓我慢慢去學Ruby,所以就是學習的方式是看到程式碼有什麼不懂在去網路上翻ruby的資料。

這邊先大概提一下程式的架構,我們採用的設計是Page Object Pattern:

Page Object Pattern:

Within your web app’s UI there are areas that your tests interact with. A Page Object simply models these as objects within the test code. This reduces the amount of duplicated code and means that if the UI changes, the fix need only be applied in one place.

採這個設計的好處可以讓我們減少重複的程式碼更好維護、簡潔。

Ruby :

Example —Videopass (產品) on web,這頁是 Unlimited page

Videopass on web

我們將每頁可共用的區塊拆成各自獨立的元件,實作成 Ruby 的 module,如此就不用重複維護同樣的程式碼;至於 module 跟 class 的差異就請參考這篇。以下舉例使用 Page Object Pattern 時,可以共用的 module:

header

item_group

這幾個部分在別的頁面也可以使用到,因此把他們抽出來實作,再來把每一頁的 Page Object 實作出來。

Selenium Grid :

Selenium Grid是一個Hub-Node的架構,我們對Hub下指令,Hub會基於我們的指令對要求的Node進行測試,運用Selenium Grid可以讓我們對遠端Browser下指令執行平行化測試、集中化管理、跨平台等優點

(這邊不多作介紹,欲知更詳細可以到Selenium Grid wiki上查看)

[9–10月]撰寫、維護Ruby code架構

hub:iMac, Node1:iMac, Node2:Win10, Node3:Win8.1(vm on Win10)
Jobs on jenkins

這是前一位實習生建置環境的架構,稍微舉例說明一下,假設我們要測的是Firefox,我們會透過jenkins去對Hub(架在iMac上)下達執行測試的指令,Hub會在對連接上的Node2(Win10)下request,在Node2上啟動Firefox做測試,我們就可以看到Firefox瀏覽器自動開啟並執行測試。

iMac太多測試人員再使用,決定轉換架構

第二版我們想要減輕iMac上的壓力,把jenkins、Hub改接到Win10上面

hub:Win10, Node1:iMac, Node2:Win10, Node3:Win8.1(vm on Win10)

這一切看似很美好,但可能是對Windows信仰不足,遇到了編碼問題

編碼爆炸

在網路上找了各式各樣的解法還是沒辦法解決,於是決定再次改版。

hub:Win10, Node1:iMac, Node2:Win10, Node3:Win8.1(vm on Win10)

到這邊才穩定的運行我們整個網站自動化測試的系統,不會再有太多人使用導致測試被干擾的狀況,也沒有編碼的問題。

[11–12月]建置Webdriver.io架構

在講我建置的Webdriver.io架構之前,先簡單介紹一下Webdriver.io

WebdriverIO lets you control a browser or a mobile application with just a few lines of code. Your test code will look simple, concise and easy to read. The integrated test runner let you write asynchronous commands in a synchronous way so that you don’t need to care about how to handle a Promise to avoid racing conditions. Additionally it takes away all the cumbersome setup work and manages the Selenium session for you.

Working with elements on a page has never been easier due to its synchronous nature. When fetching or looping over elements you can use just native JavaScript functions. With the $ and $$functions WebdriverIO provides useful shortcuts which can also be chained in order to move deeper in the DOM tree without using complex xPath selectors.

The test runner also comes with a variety of hooks that allow you to interrupt the test process in order to e.g. take screenshots if an error occurs or modify the test procedure according to a previous test result. This is used by WebdriverIOs services to integrate your tests with 3rd party tools like Appium.

  • End to end Testing Framework
  • Based on Node.js
  • Synchronous command handling
  • Supports a variety of hooks

它是一個 End to end 的Testing Framework,由Node.JS開發,而且是以同步的方式來去執行我們的測試程式,也支援了多樣的hooks來更方便地讓我們寫測試程式,可以用來跑手機、網站的測試,像我們這邊測網站的話,它會透過 Selenium 的 RESTful API 來做溝通。

測試網站、手機(Android、ios)

Extendable:

我們可以輕易的擴充指令,像是我們想要增加一個指令就能拿到 url 及 title,我們可以運用 browser.addCommand('getUrlAndTitle') 方法來去新增(參考 addCommand.js),下面使用 browser.getUrlAndTitle() 就能一次拿到 url 及 title(參考 example.js)。

Compatible:

整合了大部分的 TDD 及 BDD 測試框架,像是本篇我們用到的 cucumber 以及常見的 mocha、Jsamine。

Feature-Rich:

測試請求的流程:

這邊舉個流程的例子,假設我們要透過 webdriver.io 去開啟 http://example.org 這個網址,寫一段 code browser.url('http://example.org') 並執行,webdriver.io 會透過Selenium 的 RESTful API 發送請求, Selenium server 接到後會在對應的 node 開啟瀏覽器並連到 http://example.org 這個網址,接著再將結果回傳到 webdriver.io。

支援多種Cloud Services(指的是可以不用自己購買硬體的設備,直接透過網路來操作運用雲端服務提供的測試設備)

支援多種 Reporters(不同的測試結果格式):

Webdriver.io 的介紹在這邊告一個段落,以下是我建置的webdriver.io + cucumber架構

Webdriverio專案建置

先看到features的這個資料夾, 裡面總共13個features

而step-definitions裡面有4個steps

Feature Introduction

Every .feature file conventionally consists of a single feature. A line starting with the keyword Feature followed by free indented text starts a feature. A feature usually contains a list of scenarios. You can write whatever you want up until the first scenario, which starts with the word Scenario (or localized equivalent; Gherkin is localized for dozens of languages) on a new line. You can use tagging to group features and scenarios together independent of your file and directory structure.

Every scenario consists of a list of steps, which must start with one of the keywords Given, When, Then, But or And. Cucumber treats them all the same, but you shouldn’t. Here is an example:

Step definitions

For each step Cucumber will look for a matching step definition. Each step definition consists of a keyword, a string or regular expression, and a block.

This step definition uses a regular expression with one match group — (\d+). (It matches any sequence of digits). Therefore, it matches the first line of the scenario. The value of each matched group gets yielded to the block as a string. You must take care to have the same number of regular expression groups and block arguments. Since block arguments are always strings, you have to do any type conversions inside the block, or use Step Argument Transforms.

When Cucumber prints the results of the running features it will underline all step arguments so that it’s easier to see what part of a step was actually recognised as an argument. It will also print the path and line of the matching step definition. This makes it easy to go from a feature file to any step definition.

Test Architecture

簡單來說,Feature:模仿使用者操作的我們網站功能的流程,Steps:描述一個步驟。

再來看到pages資料夾,裡面是我們Page Object與module的程式碼

這邊用網站中的其中一頁來舉例:

對應的架構是

對應的程式碼就是

再來介紹最後一個比較重要的資料夾, lib/web_element_table,裡面放著網頁上面Dom物件的xpath,用來取得該Dom。

以上就是建置webdriver.io整體大架構的設計,忙了我一個多月XD

webdriver.io測試範例:

再來的最後兩個月就是在穩定、維護就跟新的這兩個系統,然而這幾個月下來也有採到一些雷,最後再做這一個分享:

我難過的不是程式寫不出來,而是每一個browser driver支援api程度不一樣
我難過的不是程式寫不出來,而是每一個browser driver支援api程度不一樣

每一家browser driver實作的操作不太一樣,基本上都會發摟 w3c webdriver 所制定的標準走,但是這就造成有一些 webdriver.io 的 api 無法在特定的 browser 上運行,像是我們想要用滑鼠拖拉物件,使用 webdriverio 的api : browser.dragAndDrop() 在 chrome 上就可以順利拖拉,在 Firefox 、 Safari 上就會說 moveTo() 這個功能無法執行,為了要讓每一個browser都可以順利跑我們測試,沒有實作的功能我們只能用browser.execute() 裡面塞入前端網頁可以跑的javascript去讓它執行。

再來一個是我們測試的網站有使用HTTP authentication,但是在輸入帳號密碼這一步在Safari上無法透過selenium去執行,所以safari有好一段時間無法被測試...最後的解法是跟RD、PO溝通,把HTTP authentication拿掉,改成用ip白名單的方式,去測試我們的網站。

最後來秀一下我建置的成果:

完成了chrome、Firefox的job
讓測試執行的更穩定、更有效率

最後我想要謝謝在這半年來照顧我QA team的大家,其中要特別感謝Jersey、Louis、Paul三位大大,沒有你們就不會有這半年來美好的回憶,謝謝!

後記

如果想要這個實習機會的話可以看看 KKStream 的官網,或是 KKBOX 的 104 人力銀行頁面,另外我也有分享一些面試心得在這裡

--

--

yysu
BlendVision

AWS Certified All-5 | CKA & CKAD | Ex - Cloud Engineer @ AWS