今天給大家分享的主題的是Javascript&QA⼯程師。看到這個主題,可能有人問:前端開發完就OK了,剩下的丟給測試就行,哪裡還需要關心這些?但事實上呢,測試是前端開發非常重要的環節,也是邁向進階前端工程師的必經之路!
本文主要分為一下四個部分:
· 單元測試
· 效能測試
· 功能測試
· 安全性測試
一. 單元測試
單元測試(unit testing),是指對程式中的最小可測試單元進行檢查和驗證。對於單元測試中單元的含義,一般來說,要根據實際情況去判定其具體含義,如C語言中單元指一個函數,Java裡單元指一個類,圖形化的軟體中可以指一個視窗或一個菜單等。總的來說,單元就是人為規定的最小的被測功能模組。單元測試是在軟體開發過程中要進行的最低層級的測試活動,軟體的獨立單元將在與程式的其他部分相隔離的情況下進行測試。
在一種傳統的結構化程式設計語言中,比如C,要進行測試的單元一般是函數或子過程。在像C++這樣的物件導向的語言中, 要進行測試的基本單元是類。對Ada語言來說,開發人員可以選擇是在獨立的過程和函數,還是在Ada包的層級上進行單元測試。單元測試的原則同樣被擴充到第四代語言(4GL)的開發中,在這裡基本單元被典型地劃分為一個菜單或顯示介面。
經常與單元測試聯絡起來的另外一些開發活動包括代碼走讀(Code review),靜態分析(Static analysis)和動態分析(Dynamic analysis)。靜態分析就是對軟體的原始碼進行研讀,尋找錯誤或收集一些度量資料,並不需要對代碼進行編譯和執行。動態分析就是通過觀察軟體運行時的動作,來提供執行跟蹤,時間分析,以及測試覆蓋度方面的資訊。
對於前端來說就是一個函數。
(1)前端為什麼要做單元測試?
我認為主要原因為一下5點:
1.正確性
測試可以驗證代碼的正確性,在上線前做到心裡有底。
2.自動化
當然手工也可以測試,通過console可以列印出內部資訊,但是這是一次性的事情,下次測試還需要從頭來過,效率不能得到保證。通過編寫測試案例,可以做到一次編寫,多次運行。
3.解釋性
測試案例用於測試介面、模組的重要性,那麼在測試案例中就會涉及如何使用這些API。其他開發人員如果要使用這些API,那閱讀測試案例是一種很好地途徑,有時比文檔說明更清晰。
4.驅動開發,指導設計
代碼被測試的前提是代碼本身的可測試性,那麼要保證代碼的可測試性,就需要在開發中注意API的設計,TDD將測試前移就是起到這麼一個作用。
5.保證重構
互連網行業產品迭代速度很快,迭代後必然存在代碼重構的過程,那怎麼才能保證重構後代碼的品質呢?有測試案例做後盾,就可以大膽的進行重構。
(2)單元測試原則&測試風格
單元測試的目的是為了讓開發人員明確的知道代碼結果,原則有三點:單一職責,介面抽象,層次分離。而單元測試必備的東西是斷言庫,斷言庫是保證最小單元能否正常啟動並執行檢測方法。
測試風格:測試驅動開發(Test-Driven Development,TDD)、(BehaviorDriven Development,BDD)行為驅動開發均是敏捷開發方法論。
TDD關注所有的功能是否被實現(每一個功能都必須有對應的測試案例),suite配合test利用assert('tobi' == user.name);
BDD關注整體行為是否符合整體預期,編寫的每一行代碼都有目的提供一個全面的測試案例集。expect/should,describe配合it利用自然語言expect(1).toEqual(fn())執行結果。
(3)單元測試架構
單元測試的主要架構:
(3)單元測試運行流程
每一個測試案例組通過 describe進行設定
1.before單個測試案例(it)開始前
2.beforeEach每一個測試案例開始前
3.it定義測試案例 並利用斷言庫進行
設定chai如:expect(x).to.equal(true);非同步mocha。
4.以上專業術語叫mock
(4)自動化單元測試 karma
Karma是Testacular的新名字,在2012年google開源了Testacular,2013年Testacular改名為Karma。Karma是一個讓人感到非常神秘的名字,表示佛教中的緣分。這個名字和LOL中的扇子媽同名 - -,比較佛系。
On the AngularJS team, we rely on testing and we always seek better tools to make our life easier. That‘s why we created Karma - a test runner that fits all our needs.
Karma是一個基於Node.js的JavaScript測試執行過程管理工具(Test Runner)。該工具可用於測試所有主流Web瀏覽器,也可整合到CI(Continuous integration)工具,也可和其他代碼編輯器一起使用。
可以產生報告和單測覆蓋率檢查。
Karma.conf.js
// Karma configuration// Generated on Thu Mar 22 2018 20:30:24 GMT+0800 (CST)module.exports = function(config) { config.set({ // base path that will be used to resolve all patterns (eg. files, exclude) basePath: '', // frameworks to use // available frameworks: npmjs.org/browse/keyword/karma-adapter frameworks: ['jasmine'], // list of files / patterns to load in the browser files: [ './unit/**/*.js', './unit/**/*.spec.js' ], // list of files / patterns to exclude exclude: [ ], //指定對應的JS檔案 去執行代碼的覆蓋率 preprocessors: { './unit/**/*.js': ['coverage'] }, // test results reporter to use // possible values: 'dots', 'progress' // available reporters: npmjs.org/browse/keyword/karma-reporter reporters: ['progress', 'coverage'], coverageReporter: { type : 'html', dir : 'coverage/' }, // web server port port: 9876, // enable / disable colors in the output (reporters and logs) colors: true, // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, // enable / disable watching file and executing tests whenever any file changes autoWatch: false, // start these browsers // available browser launchers: npmjs.org/browse/keyword/karma-launcher browsers: ['PhantomJS'], //黑窗小獨立的運行環境 singleRun: true, // Concurrency level // how many browser should be started simultaneous concurrency: Infinity })}
單元測試demo:
// index.jswindow.test = function (num) { if(num == 1){ return 1 }else{ return num + 1; }}// index.spec.jsdescribe("測試基本的函數API",function(){ it("+1函數的應用",function(){ expect(window.test(1)).toBe(1); });});
二. 功能測試
功能測試主要是e2e測試。端到端測試是一種用於測試應用程式的流程是否從開始到結束執行的方法。執行端到端測試的目的是識別系統依賴性,並確保在各種系統組件和系統之間傳遞正確的資訊。
通俗點說,就是把整個系統當作一個黑盒,測試人員類比真實使用者在瀏覽器中操作UI來測試。
常見的幾種e2e測試架構,今天主要講selenium,因為phantomjs,無頭瀏覽器不在維護,所以rize與其形成犄角之勢。可以在終端進行端對端測試。
Nightwatch是一個功能非常強大,配置巨複雜的端對端測試架構,vue-cli就是用的night watch。
(1)Selenium
Selenium 是一個用於Web應用程式測試的工具。Selenium測試直接運行在瀏覽器中,就像真正的使用者在操作一樣。支援的瀏覽器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。這個工具的主要功能包括:測試與瀏覽器的相容性——測試你的應用程式看是否能夠很好得工作在不同瀏覽器和作業系統之上。測試系統功能——建立迴歸測試檢驗軟體功能和使用者需求。支援自動錄製動作和自動產生 .Net、Java、Perl等不同語言的測試指令碼。
Selenium是ThoughtWorks公司的一個強大的開源Web功能測試工具系列,採用Javascript來管理整個測試過程,包括讀入測試套件、執行測試和記錄測試結果。它採用Javascript單元測試工具JSUnit為核心,類比真實使用者操作,包括瀏覽頁面、點選連結、輸入文字、提交表單、觸發滑鼠事件等等,並且能夠對頁面結果進行種種驗證。也就是說,只要在測試案例中把預期的使用者行為與結果都描述出來,我們就得到了一個可以自動化啟動並執行功能測試套件。(Selenium的核心是Javascript寫的,他和瀏覽器進行通訊,把測試案例的資訊發送給瀏覽器執行,從而達到自動化測試的目的。)
我這裡是用Firefox測試的,需要先下載一個driver,geckdriver。然後nmp i selenium-webdriver --save;
這裡用代碼控制開啟Firefox,找到name為‘wd’的元素並鍵入‘node’,然後按會車,最後退出Firefox。代碼如下:
const {Builder, By, Key, until} = require('selenium-webdriver');(async function example() { let driver = await new Builder().forBrowser('firefox').build(); try { await driver.get('www.baidu.com/'); await driver.findElement(By.name('wd')).sendKeys('node', Key.RETURN); await driver.wait(until.titleIs('node_百度搜尋'), 1000); } finally { await driver.quit(); }})();
使用rize架構,寫法更為簡潔:
const Rize = require('rize');const rize = new Rize();rize .goto('github.com/') .type('input.header-search-input', 'node') .press('Enter') .waitForNavigation() .assertSee('Node.js') .end();
三. UI測試
前端,作為一個傳統的頁面仔,自己寫的樣式,心裡得有點B數,不能老等著人家UI走查,說你哪哪差幾像素。
這裡給大家介紹一個神奇的架構 BackstopJs。
BackstopJS automates visual regression testing of your responsive web UI by comparing DOM screenshots over time.
Backstop設定檔,backstop.json。
{ "id": "天驕", "viewports": [ { "label": "phone", "width": 375, "height": 667 }, { "label": "tablet", "width": 1024, "height": 768 } ], "onBeforeScript": "chromy/onBefore.js", "onReadyScript": "chromy/onReady.js", "scenarios": [ { "label": "qq", "cookiePath": "backstop_data/engine_scripts/cookies.json", "url": "http://map.qq.com/m/", // 這裡是待測試的UI介面URL "referenceUrl": "", "readyEvent": "", "readySelector": "", "delay": 0, "hideSelectors": [], "removeSelectors": [], "hoverSelector": "", "clickSelector": "", "postInteractionWait": "", "selectors": [], "selectorExpansion": true, "misMatchThreshold" : 0.1, "requireSameDimensions": true } ], "paths": { "bitmaps_reference": "backstop_data/bitmaps_reference", "bitmaps_test": "backstop_data/bitmaps_test", // 這裡放UI的設計圖 "engine_scripts": "backstop_data/engine_scripts", "html_report": "backstop_data/html_report", "ci_report": "backstop_data/ci_report" }, "report": ["browser"], // 報表的方式,這裡是瀏覽器 "engine": "chrome", "engineFlags": [], "asyncCaptureLimit": 5, "asyncCompareLimit": 50, "debug": false, "debugWindow": false}
測試的結果頁面非常友好,她會把你的介面和UI圖的差異標註出來:
三. 效能測試
下面說下效能測試。
前端效能主要分為兩部分,第一是頁面效能,如秒開率等,第二是代碼效能。今天主要說代碼效能。
今天主要講代碼效能測試 benchmarkjs,A benchmarking library that supports high-resolution timers & returns statistically significant results
字面意思理解,支援高解析度計時器的基準測試庫,並返回統計上顯著的結果。
面向切面編程AOP無侵入式統計。Benchmark基準測試方法,它並不是簡單地統計 執行多少次測試代碼後對比時間,它對測試有著 嚴密的抽樣過程。執行多少次取決於採樣到的數 據能否完成統計。根據統計次數計算方差。
話不多說,直接看代碼:
var Benchmark = require('benchmark');var suite = new Benchmark.Suite;suite.add('使用正則匹配字串', function() { /o/.test('Hello World!'); }) .add('使用字串尋找', function() { 'Hello World!'.indexOf('o') > -1; }) //添加監聽 .on('cycle', function(event) { console.log(String(event.target)); }) //執行結果 .on('complete', function() { console.log('更快的是-》 ' + this.filter('fastest').map('name')); }) // run async .run({ 'async': true });
執行結果如下:
下面說下 壓力測試。
對網路介面做壓力測試需要檢查的幾個常用指標有吞吐率、回應時間和並發數,這些指標反映了伺服器並發處理能力。
PV網站當日訪問人數 UV獨立訪問人數。PV每天幾十萬甚至上百萬就 需要考慮壓力測試。換算公式QPS=PV/t ps:1000000/ 10*60*60=27.7(100萬請求集中在10個小時,伺服器每秒處理27.7 個業務請求);
ab -c 100 -n 100 http://localhost:8001 每秒持續發出28個請求。
Request per second 表示伺服器每秒處理請求數 即為QPS
。Failed requests 表示此次請求失敗的請求數 理論上壓測值越大增加
Connection Times 連線時間,它包括用戶端向伺服器端建立串連、服 務器端處理請求、等待報文響應的過程。
常用的壓力測試工具是ab、siege、http_load。
四. 安全性測試
常見的安全攻擊有三種:XSS, CSRF, SQL注入。
(1)XSS 跨網站指令碼攻擊
在input中輸入未閉合標籤,測試是否會執行。
><scrīpt>alert(document.cookie)</scrīpt>
(2)CSRF,Sql注入。
Sql注入。 ' or 1=1- -
(3)Csrf跨站請求偽造
這是一個cookies漏洞(身分識別驗證),使用者訪問了危險網站B後,B會訪問偷偷的讓使用者訪問正規網站A。正規網站對身份進行校正後(通過cookies)認為這是同一個使用者,則進行操作
目前沒找到什麼好的測試方法。
總結:前段時間很多前端名人的部落格網站都被攻擊了,很多人吐槽前端天花板低,所以學習一門後台語言對我們前端開發人員對思維培養至關重要。而是否能寫好單測非常重要。這也是我們邁向進階前端工程師的必經之路。
最後我想說一句話:不懂測試的UI不是好前端;不懂背景產品不是好前端。前端路漫漫,吾將上下而求索。