over 1 year ago

我覺得工程最有趣的地方在於評估需求與比較方案,如何確切地列出需求與先後重要性,依此導入現行適合的最佳方案並兼具未來的拓展性需要做大量的功課,所以這篇主要紀錄我瀏覽網路上大家做前端測試的心得與流程,做了一些基本的分析與比較,個人沒有寫測試的經驗,所以如果有觀念錯誤或是補充煩請指教。

測試的總體概念

  1. 從心法TDD/BDD作為出發,用規格結合測試主導整個專案的開發,除了保持程式碼都在良好測試覆蓋外,也避免專案發散
  2. 到基本測試面向:Unit Test / End-to-End Test,Unit Test主要測試各個函式的功能性是否正確,而E2E Test專注於整個使用者流程是否會出錯,比較偏向整合測試。
  3. 接著就是滿山滿谷的JS Tools的選擇,最基本的測試框架,例如Mocha / Jasmine / Tape / Jest(Airbnb開發)等,基本上都大同小異,主要定義測試內容、提供人性化的函式命名並結合基本的值比較,本人直接選定Mocha,因為後端NodeJS也合用;選定測試框架後就可以編寫Unit Test。
  4. E2E Test最大重點在於模擬使用者在瀏覽器中操作網頁的流程,像是按按鈕、填寫表單等,以使用者行為導向做一整套的測試,這裡可以分成兩大部分:沒畫面跟有畫面;
    沒畫面:採用headless browser進行模擬,基本上就是去除介面的瀏覽器,但是同樣有產生DOM(與先前Unit Test最大差異),這部分工具有PhantomJS / JSDom;另外補充 headless browser搭配NodeJS是爬蟲程式的常用解法。
    有畫面:直接觸發系統的瀏覽器,自動操作瀏覽器,所以是跑在一般使用者會用的瀏覽器上,這部分有老牌的SeleniumKarma,Selenium後續補充,Karma則是Angular Team採用的測試工具,同樣可以搭配Mocha等測試框架;這部分網路上有很多雲端服務,如Sauce lab,他背後採用Selenium,會自動幫你跑測試並錄影,有免費試用的額度。
    採用headless browser跑最大好處就是快,但缺點就是你看不到真實的畫面,例如有時瀏覽器渲染CSS的方式不同,可能會有差異,這就必須要真的跑在瀏覽器上才知道。
  5. React headless E2E Test:React要做E2E測試比較麻煩的地方在於他是由JS產生DOM,不能直接做測試,所以必須要有工具先將React Component直接渲染成DOM,React官方有釋出react-addons-test-utils但是不太推(看其他人講的),所以主流採用Enzyme,這是由Airbnb開發並釋出的工具。
    接著搭配JSDom進行E2E Test,詳細內容請參考 Testing React Components with Enzyme and Mocha

總結:TDD/BDD -> 測試框架Mocha -> Unit Test編寫 -> E2E Test (headless or not)

Selenium介紹

Selenium介紹影片請參考 Selenium Test Automation: Practical Tips & Tricks - with Dave Haeffner ,非常詳細且全面,兩部一個多小時可以有個總體概念。
採用Selenium最大原因就是我希望看到真實的網站操作畫面,並自動跑在IE/Chrome/Firefox/Safari瀏覽器。
Selenium是用Java所開發,所以最一開始也只能用Java寫測試檔,但是現在已經可以用Python/C#/NodeJS等編寫,相當方便。
Selenium2.0中有兩個工具
Selenium IDE:一開始是在Firefox上的外掛,可以用GUI的方式規劃測試流程,本篇不提,影片也不推薦使用;
Selenium WebDriver有兩個部分:

  1. 編寫測試流程的核心,諸如選取DOM Element、輸入資料、點選按鈕都需要這個核心函式庫,各自語言有各自的函式庫可以安裝;
  2. 各家瀏覽器的驅動程式,每個瀏覽器都有各自的安裝檔如ChromeDriver etc,每家瀏覽器各自維護,這部分必須先安裝才能使用,請參考Selenium WebDriver。 另外Selenium提交W3C成為Draft,所以可靠性大大保證(連微軟都宣布跟著走了

補充一個Selenium Grid:通常跑測試不會只跑一個瀏覽器,如果想要一次監管多的測試就可以用Grid,採用Hub/Node方式,在Node上跑Webdriver並統一連到Hub一次監管,在Selenium 2.0已經併入核心,不用額外安裝。

簡單總結,要操作Selenium的先決條件是在系統安裝瀏覽器與相對應的Webdriver,接著編寫測試檔並載入相對應語言的Webdriver library,在Nodejs中有官方釋出的selenium-webdriver;另外在JS中還有像是NightwatchWebdriverIO封裝了Selenium API的函式庫可以選用,但我個人覺得有官方認證的就用官方的,其他兩個簡單看完quick start沒有什麼太大的驚艷(有待強者補充)。

Why Docker

Docker採用Container虛擬化技術,可以快速啟動同時保持主機與虛擬化的隔離性,最棒的是建立好Image不論是要輸出到Linux、Windows還是Mac,只要主機可以執行Docker Engine就可以保證執行的一致性,要做佈建或是水平擴展都極其方便!
之所以採用Docker還有個原因在於 可以執行多個不同版本的瀏覽器,每個瀏覽器相對應的Webdriver都可以驅動系統的瀏覽器,但是如果你安裝多個版本的同家瀏覽器也只會驅動一個而已,這時候只要跑多個Docker Image就可以避免這個問題;而且通常Test Server會獨立於開發Server,使用docker-machine搭配AWS或是Digital Ocean都可以做到遠端佈建。

關於Selenium Docker這部分,有強大的工程師已經建立好一系列的Docker Image-Selenium Docker (膜拜OTZ;Youtube上有詳細的系列教學 Introduction to Selenium grid with Docker,看完就會基本的使用;
目前提供Chrome和Firefox,順手查了一下瀏覽器目前市佔率The Most Popular Browsers,這兩者加起來逼近九成,,IE穩定下滑(IE must dead! 這份報告雖然是W3Schools提供,但感覺有點詭異,少了Edge就不太對啊... 不過就稍做參考囉。
另外Chrome Driver也提供Android Web View測試,後續會實作,至於Safari和iOS就先等等囉。

講這麼多,一個測試都還沒開始寫XD 以下進入實作

建立Docker Image開始 - Firefox

純操作影片請參考 Selenium test demo

// 確定docker已安裝
$ docker -v
// 直接抓取官方Image,這裡就可以跳下一步
// 4444 是 Selenium standalone server port
// 5900 是 VNC Server port
$ docker run -d -p 4444:4444 -p 5900:5900 selenium/standalone-firefox-debug:3.0.1-aluminum

// 自己從最底層開始Build
$ docker run -it --name=selenium-test ubuntu
// 安裝vnc
// 安裝java jdk , selenium-standalone(包含RemoteControl Server)
// 安裝firefox

接著,記得先開VNC Viewer,在Mac可以打開Safari在搜尋列輸入vnc:\\127.0.0.1:5900,會自動跳出內建程式並輸入secret為預設密碼。此時應該只有個Ubuntu背景桌布。

編寫測試

// 來自於 npm [selenium-webdriver](https://www.npmjs.com/package/selenium-webdriver)

// 記得要先 npm install selenium-webdriver -g

var webdriver = require('selenium-webdriver'),
    By = webdriver.By,
    until = webdriver.until;

var driver = new webdriver.Builder()
    .forBrowser('firefox')
    .usingServer('http://localhost:4444/wd/hub')
    .build();

driver.get('http://www.google.com/ncr');
driver.findElement(By.name('q')).sendKeys('webdriver');
driver.findElement(By.name('btnG')).click();
driver.wait(until.titleIs('webdriver - Google Search'), 1000);
driver.quit();

基本的測試大概就是這樣,Chrome也是。

Android

Host要安裝ChromeDriver、Android SDK、ADB Tool,且必須連接有開發模式的Android實體手機。
因為我Host是Mac,目前找不到有效方法可以讓Docker讀取到手機,所以我就跑在Mac上。
Chrome Driver下載Android SDK- Get just the command line toolsADB install
記得要將chromedriver和tools路徑加入~/.bash_profile
接著連上手機,輸入

//確認手機可以連,會列出可以用的裝置,如果裝置出現 unauthorized,那就是還沒設定為開發者模式
$ adb devices
 
$ adb start-server

接著是測試,此時加入setChromeOptions並移除usingServer即可

var webdriver = require('selenium-webdriver'),
    chrome = require('selenium-webdriver/chrome'),
    By = webdriver.By,
    until = webdriver.until;


var driver = new webdriver.Builder()
    .forBrowser('chrome')
    .setChromeOptions(new chrome.Options().androidChrome())
    .build();

driver.get('http://www.google.com/ncr');
driver.findElement(By.name('q')).sendKeys('webdriver');
driver.findElement(By.name('btnG')).click();
driver.wait(until.titleIs('webdriver - Google Search'), 1000);
driver.quit();

輸入完,理論上實體手機上就會開始自動執行測試了。

總結

這一篇主要紀錄前端測試的整體觀念,並簡單使用Selenium做E2E Test(比較像是Demo)。

← JS - 關於Object、Function的屬性、作用域與種種 WebRTC-介紹與實戰 →
 
comments powered by Disqus