用Node.js撰寫CSS測試
目前主流CSS的測試方法都是「截圖比對」,這跟一般寫測試的邏輯不太一樣。
因為撰寫CSS測試是一件拐彎抹角的事情,主要是測試大多以「是否完成某個目的」為判斷基準。但對於CSS測試來說,CSS完全是排版的東西,很難有一個目的來判斷,例如我們可以測試1+1是否等於2
但卻很難測試這個div是否距離左邊3px
,一來會有優先權的問題導致某些設定好的數值無法發揮效果,二來又會有z-index等不同的因素導致DOM互相遮蔽。
因此,目前最主流的測法就是用截圖,直接用最後的執行結果畫面當做比對基準,先截一張圖當做標準,再用第二張圖來比對。
BackstopJS demo
這邊簡單用BackstopJS
當做範例,示範要如何進行CSS測試。由於要測試CSS一定都跟前端有關,所以目前有在檯面上的CSS測試framework幾乎都是用javascript所寫。CSS-Tricks上有非常詳盡的說明,但有點過於囉嗦,我這邊稍微整理一下。
安裝
這部份最囉嗦,因為本人對NodeJS並沒有很熟,導致踩到很多地雷。首先要確定所有相關套件都有裝上。
NodeJS
$ brew install node
$ node --version (確認有安裝成功)
Bower
$ npm install -g bower
$ bower --version
PhantomJS
$ npm install -g phantomjs
$ phantomjs --version
CasperJS
$ npm install -g casperjs
$ casperjs --version
Gulp
$ npm install -g gulp
$ gulp --version
如果你的brew不是安裝在root底下,所有npm要安裝的內容都會需要加上sudo
,這比較是個人習慣問題,沒有強迫的方式。
這邊要提醒一下,如果沒有加上-g
,就會在你當前的資料夾底下新增node_modules
資料夾,並把套件裝在裡面,這會造成之後的安裝有問題。因為npm管理套件是以資料夾為單位,如果你的上層已經有node_modules
資料夾,他會把目前的資料夾當做子資料夾,而去抓上層的node_modules
資料夾。請務必確認node_modules
資料夾只會存在於你的專案資料夾內,就像你不會把自己的系統根目錄放一個.git
資料夾一樣。
產生專案設定檔
要到你的一個專案資料夾內(開一個新的空專案也可),在專案的根目錄底下執行(請注意執行的資料夾位置,這會影響到後續的步驟):
$ bower install backstopjs
$ cd bower_components/backstopjs
$ npm install
$ gulp genConfig
順利的話會出現一個backstop.json
的檔案,但他並不會出現在目前的資料夾內,而是出現在專案資料夾的根目錄內,所以請執行:
$ cd ../..
$ ls
順利的話就會看到backstop.json
檔案。
設定
設定檔分為兩塊,首先看到viewports
的部份:
"viewports": [
{
"name": "phone",
"width": 320,
"height": 480
},
{
"name": "tablet_v",
"width": 568,
"height": 1024
},
{
"name": "tablet_h",
"width": 1024,
"height": 768
}
]
這部份代表你要測試的裝置列表,這三個裝置都是手機和平板,你可以自行加上桌機的寬高,記得不要把json格式打亂,要將所有裝置都塞在viewports數列內。
"scenarios": [
{
"label": "https://getbootstrap.com",
"url": "https://getbootstrap.com",
,"hideSelectors": [
]
,"removeSelectors": [
]
,"selectors":[
"nav"
,".jumbotron"
,"body .col-md-4:nth-of-type(1)"
,"body .col-md-4:nth-of-type(2)"
,"body .col-md-4:nth-of-type(3)"
,"footer"
],
"readyEvent": null,
"delay": 500
}
]
這邊有幾個可以修改的部份,但最主要會用到的有幾個:
label
:你的測試要叫什麼名字url
:抓取的位址hideSelectors
:主要用於測試動態內容,因為許多網頁DOM會從資料庫抓檔案,動態內容的截圖必定會比對錯誤,所以我們可以隱藏動態內容顯示的地方。例如顯示隨機文章的欄位,我們要將文章內容隱藏,只擷取文章的外框,則可以填入css selector"div.container .post-content"
,而在下面selector的欄位,填入"div.container"
,這樣他就只會抓取container class的div,而會忽略裡面post-content class的div。removeSelectors
:如果網頁內的DOM會有無法預期的大小,例如隨機寬高,那這裡可以填入該元素,他便會設定該元素為"display: none"
直接省略。同樣使用css selector寫。selectors
:使用的css selector名稱,可以用一般的.
代表class、#
代表id
.6 delay
:進入網頁以後需要等待多久再開始抓取,一般預設的500其實已經足夠,除非網頁肥大或有許多ajax request需等待完成,這時才需要較久的時間。
預設的設定檔可以看到他會去https://getbootstrap.com
抓取資料,假如我們依照自己的需求修改完成,這時在專案根目錄底下的/bower_components/backstopjs
執行:
$ gulp reference
記得,如果執行的目錄位置不對,他會請你npm install
,如果你已經裝過了,請確認執行的位置是否正確即可。如果不小心再npm install一次,會產生其他的node_modules
資料夾,這些都會產生混淆和錯誤。
假如沒發生錯誤的話,這個指令會把要比對的資料先擷取圖片,存檔,當做判斷基準。這時再執行:
$ gulp test
這時他會用https://localhot:3001
開啟一個網頁,裡面就是我們的測試內容,他會逐一比對跟reference所抓的圖片是否有任何不同。
其他
CSS測試跟一般軟體測試最大的不同在於他沒有TDD,一定要先把網頁內容寫好,才能用截圖的方式產生reference。也就是說CSS測試最主要的功能是修改網站設計時,預防你改一個class設計卻因為剛好有其他DOM採用相同的class而爆掉。