测试MEAN堆栈
自您啟動用戶組列表和信息(UGLI)應用程序以來,已經走了很長一段路。 您正在將本地數據存儲在應用程序中,并通過RESTful Web服務提取遠程數據。 該應用程序具有可移動的響應式Web設計 ,并且對其進行了語義標記,以充分利用搜索引擎優化(SEO)。 對于身份驗證 ,用戶可以創建本地專用帳戶,也可以(通過OAuth)重用存儲在其他位置的現有帳戶。
但是,如果沒有可靠的測試套件作為您的安全網,將UGLI應用程序投入生產時您會感到不舒服嗎? 當然不是。 那在專業上是不負責任的。 我同意Neal Ford(作者兼國際發言人)的觀點,他稱測試為“軟件開發的工程嚴謹性”。 每當我開始與新客戶互動時,我都會先關注他們的測試套件,甚至是他們的設計文檔。 測試的質量,數量和全面性與軟件開發過程的成熟度有著直接的關系。 健康,積極維護的測試套件是項目整體健康的關鍵。 同樣,任何將可測試性放在首位的框架都移到了我的清單頂部。 AngularJS是由測試人員編寫的,我很難想到另一個易于測試的現代Web框架。 MEAN.JS堆棧擴展了現成的可測試性,包括對服務器端邏輯的測試。
“ AngularJS是由測試人員編寫的,我很難想到另一個易于測試的現代Web框架。 ”
在本系列的開始,我向您介紹了MEAN堆棧的基本構建模塊— 松散地連接在一起的小塊組成了應用程序的生產組件。 現在是時候對各種框架和庫執行相同的操作了,這些框架和庫將用于測試您的應用并使之準備就緒。 我將向您介紹Karma :可插拔的測試運行程序,它使在任何測試框架中編寫的測試在任意數量的真實Web瀏覽器(包括智能手機,平板電腦和智能電視)上運行并返回各種結果的過程變得微不足道。格式。 在此過程中,您將使用Jasmine進行客戶端測試,使用Mocha進行服務器端測試,并使用伊斯坦布爾進行代碼覆蓋。
運行測試
因為您一直在使用MEAN.JS框架附帶的Yeoman生成器,所以您已經準備好了幾個生成的測試。 輸入grunt test來運行它們。 您應該看到與清單1相似的結果。
清單1.運行生成的測試
$ grunt test Running "env:test" (env) taskRunning "mochaTest:src" (mochaTest) taskApplication loaded using the "test" environment configurationRunning "karma:unit" (karma) task INFO [karma]: Karma v0.12.31 server started at http://localhost:9876/ INFO [launcher]: Starting browser PhantomJS INFO [PhantomJS 1.9.8 (Mac OS X)]: Connected on socket 6zkU-H6qx_m2J6lY4zJ8 with id 51669923 PhantomJS 1.9.8 (Mac OS X): Executed 18 of 18 SUCCESS (0.016 secs / 0.093 secs)Done, without errors.如果有錯誤或警告,請不要擔心; 測試將被支架化以匹配最初實現時的模型和控制器。 如果您一直在更改被測代碼(CUT),而不更新相應的測試,則可能會遇到錯誤。
每當單元測試失敗時,我都會很高興。 單元測試是代碼庫的斷路器。 在家里,您將斷路器放在電網和昂貴的個人電子設備之間。 這樣,當潛在的有害電涌通過電線進入時,您將損失一個35美分的斷路器,而不是一臺價值3500美元的筆記本電腦。 同樣,每個破壞單元測試都是您看到的錯誤,而您的用戶則看不到。
如果可以的話,請花點時間修復損壞的測試。 錯誤的常見來源是測試對刪除或更改的字段名稱的依賴。 服務器端測試在應用程序/測試中。 客戶端測試存儲在每個公共/模塊的測試目錄中。 如果您無法立即在測試中看到錯誤的根源,請不要刪除測試; 只需將其暫時移出目錄樹即可。
現在您可以進行干凈的測試運行了,是時候解構該過程了。
了解Grunt test任務
當您鍵入grunt test ,希望您自己問:“嗯,我想知道Grunt如何運行這些測試。” 如您所知,Grunt運行您的構建腳本。 在文本編輯器中打開gruntfile.js,并一直滾動到文件底部。 您可以看到正在注冊的test任務:
// Test task. grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);grunt.registerTask的第一個參數是任務的名稱,在本例中為test 。 下一個參數是一組相關任務。 test任務首先設置特定于測試環境的值,然后運行用Mocha編寫的所有服務器端測試,最后通過Karma啟動客戶端測試。
在gruntfile.js中向上滾動直到找到env任務:
env: {test: {NODE_ENV: 'test'} },此任務只需NODE_ENV變量設置為test 。 回想一下,此變量可幫助Grunt確定哪些特定于環境的設置(在本例中為config / env / test.js)與config / env / all.js中的常用設置合并。
如果您在文本編輯器中查看config / env / test.js(如清單2所示),您將看到一個自定義的MongoDB連接字符串,以及各種OAuth提供程序的所有Passport設置的鉤子:
清單2. config / env / test.js
'use strict';module.exports = {db: 'mongodb://localhost/test-test',port: 3001,app: {title: 'Test - Test Environment'},facebook: {clientID: process.env.FACEBOOK_ID || 'APP_ID',clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',callbackURL: 'http://localhost:3000/auth/facebook/callback'},google: {clientID: process.env.GOOGLE_ID || 'APP_ID',clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',callbackURL: 'http://localhost:3000/auth/google/callback'},// snip };本部分將是您將Passport指向Meetup身份驗證策略的模擬實現的理想場所。 這樣一來,您就不必依賴于在測試運行期間設置實際用戶并向Meetup.com發出實際OAuth請求。
配置測試環境后,Grunt將運行用Mocha編寫的所有服務器端測試。 這是mochaTest任務:
mochaTest: {src: watchFiles.mochaTests,options: {reporter: 'spec',require: 'server.js'} },旋鈕和轉盤
有關在進行Mocha測試時可以旋轉的旋鈕和轉盤的更多信息,請參閱grunt-mocha-test的插件文檔 。
為什么用Mocha而不是Jasmine編寫服務器端測試? Mocha的成熟度,可擴展性和插件使其成為我最喜歡的測試框架之一。 Mocha是測試Express路由,控制器和MongoDB交互之類的強大選擇。 盡管Mocha可以輕松在Node.js和瀏覽器中運行測試,但是AngularJS團隊更喜歡Jasmine進行瀏覽器內測試。 Jasmine針對客戶端測試進行了更優化,因此MEAN.JS開發人員采用了最佳方法,并選擇了一個強大的服務器端測試框架來測試服務器端,并選擇了一個強大的客戶端測試框架來測試客戶端。客戶端的事情。 您應該為選擇的測試工具交換一個或兩個框架而感到自在。
由于服務器端測試(按照定義)不在瀏覽器中運行,因此Karma不會啟動Mocha測試。 茉莉花測試(Grunt test依賴項的最后一部分)是由karma任務觸發的:
karma: {unit: {configFile: 'karma.conf.js'} }在繼續解構karma.conf.js文件之前,請在文本編輯器中打開package.json。 除了在dependencies塊中列出的運行時模塊之外,您還可以在devDependencies ( 開發人員依賴項的縮寫)塊中看到幾個構建時依賴項。 此塊專門用于在鍵入npm install時聲明和安裝與Mocha和Karma相關的Grunt插件:
"devDependencies": {"grunt-env": "~0.4.1","grunt-mocha-test": "~0.10.0","grunt-karma": "~0.8.2","load-grunt-tasks": "~0.4.0",// snip}業力介紹
我知道,業力是唯一獲得碩士論文支持的考試選手。 Karma背后的想法更為簡潔明了:該項目的任務說明:
事情應該很簡單。 我們相信測試,因此我們希望使其盡可能簡單。而且很簡單。 業力允許您在選擇的框架中編寫測試。 無論您是喜歡QUnit的測試驅動開發(TDD)樣式還是Jasmine的行為驅動開發(BDD)樣式,Karma都會很高興地運行以任何樣式編寫的測試。 (如果您希望使用單個測試框架來編寫服務器端和客戶端測試,則Karma還為Mocha提供了一流的支持。)
經驗豐富的Web開發人員知道在各種瀏覽器中測試其應用程序的重要性。 JavaScript的核心語言在所有瀏覽器中都非常一致,但是文檔對象模型(DOM)的操縱和發出Ajax請求的方式遠非標準化。 諸如jQuery和AngularJS之類的主流庫在填充瀏覽器不兼容性方面做得很好,但是這不會使您陷入虛假的自滿感。 一項測試值得一千種意見,并且證明您的應用程序可以在特定的瀏覽器中正常運行的證據要比簡單地假設能勝任得多。
Karma提供了幾個插件,可用于按需啟動真正的瀏覽器,運行完整的測試套件,然后在完成后關閉瀏覽器。 該功能很方便在您選擇的瀏覽器中本地運行測試,但是如果通過無頭的連續集成服務器(例如Jenkins,Hudson或Strider)啟動測試,則可能會受到限制。
幸運的是,您可以站起一臺運行很長時間的Karma服務器,并捕獲遠程設備上的瀏覽器。 捕獲瀏覽器就像在瀏覽器中訪問Karma服務器的URL一樣簡單。 如果瀏覽器支持Web套接字( caniuse.com在每種主流的現代瀏覽器中都顯示支持),則Karma服務器將與該設備保持長期,持久的連接。 隨著新測試被添加到套件中,Karma服務器將通過有線將它們序列化到遠程瀏覽器,運行它們并返回結果。
但是,如果無法量化結果,運行測試套件有什么好處? 業力為幾個不同的記者提供插件。 報告程序可以很簡單,就像在每次通過測試時在命令行上打印出一個點一樣。 或者,報告程序可以生成完全格式化HTML,或者發出可以轉換為您選擇的輸出的原始JUnit兼容XML。
測試框架,瀏覽器啟動器和結果報告器均在karma.conf.js文件中定義。
了解karma.conf.js
在文本編輯器中打開karma.conf.js,如清單3所示。在該文件中,您會找到標記清晰的frameworks , files , reporters browsers和browsers 。
清單3. karma.conf.js
'use strict';/*** Module dependencies.*/ var applicationConfiguration = require('./config/config');// Karma configuration module.exports = function(config) {config.set({// Frameworks to useframeworks: ['jasmine'],// List of files / patterns to load in the browserfiles: applicationConfiguration.assets.lib.js.concat(applicationConfiguration.assets.js,applicationConfiguration.assets.tests),// Test results reporter to use// Possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'//reporters: ['progress'],reporters: ['progress'],// Web server portport: 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_DEBUGlogLevel: config.LOG_INFO,// Enable / disable watching file and executing tests whenever any file changesautoWatch: true,// Start these browsers, currently available:// - Chrome// - ChromeCanary// - Firefox// - Opera// - Safari (only Mac)// - PhantomJS// - IE (only Windows)browsers: ['PhantomJS'],// If browser does not capture in given timeout [ms], kill itcaptureTimeout: 60000,// Continuous Integration mode// If true, it capture browsers, run tests and exitsingleRun: true}); };返回參考package.json。 在該文件中,您可以在devDependencies塊中找到各種Karma插件的相應條目:
"devDependencies": {// snip"karma": "~0.12.0","karma-jasmine": "~0.2.1","karma-coverage": "~0.2.0","karma-chrome-launcher": "~0.1.2","karma-firefox-launcher": "~0.1.3","karma-phantomjs-launcher": "~0.1.2"}因為所有支架式客戶端測試都是用Jasmine編寫的,所以我建議將frameworks數組保持原樣。 但是,正如您將在本節的后面看到的那樣,您可以隨意添加和刪除瀏覽器。
引入PhantomJS
如果您是一名Web開發人員,但對PhantomJS瀏覽器不熟悉,那么您將可以接受。 PhantomJS是Web測試人員最好的朋友之一。
容易被欺騙,將網絡瀏覽器視為由熟悉的品牌名稱標識的整體應用程序:Firefox,Chrome,Safari,Opera和Internet Explorer。 這些品牌名稱只是描述特定技術集合(包括渲染引擎(用于HTML和CSS),腳本引擎(用于JavaScript)和插件子系統)的便捷方式。
“現在,您是一位經驗豐富的MEAN開發人員,您已經非常熟悉將組件從瀏覽器中拔出并無頭運行它們的過程。 運行無頭渲染套件進行測試時,您應該感到賓至如歸。 ”
一旦將瀏覽器識別為渲染工具包和腳本引擎的松散集合,就會打開全新的理解水平。 例如,在1990年代中期發布2.0版時,Netscape Navigator瀏覽器擁有90%以上的市場份額。 幾年后,IE接管了該市場的領導地位。 但是,近年來,渲染工具包-WebKit-而不是瀏覽器占有多數市場份額。 這是因為直到最近(請參閱WebKit,見Blink側欄),基于WebKit的Safari,Mobile Safari,Chrome,Android瀏覽器,BlackBerry瀏覽器,Kindle設備,PlayStation,三星智能電視,LG智能電視,松下智能電視等等。 盡管這些應用程序和設備都是由不同的公司和項目組裝而成的,但它們共享一個通用的渲染工具包,用于顯示HTML和使用CSS對其進行樣式設置。
WebKit,見識眨眼
Google在2013年發布了一個新聞,宣布將分叉WebKit項目并創建一個名為Blink的單獨的渲染工具包。 不久之后,Opera宣布將停止開發其自定義渲染工具包,而采用Blink。 (此列表顯示了所有主要瀏覽器的基礎渲染工具。)
蘋果公司最初于2005年從KHTML渲染引擎派生WebKit,但現在繼續積極開發和維護該項目。 (有關更多信息,請參見Wikipedia中的WebKit條目。)
那么,這與PhantomJS有什么關系? PhantomJS網站告訴我們:
PhantomJS是可使用JavaScript API編寫腳本的無頭WebKit。無頭服務不需要監視器或GUI。 這聽起來很適合在無監視器的連續集成服務器上運行基于瀏覽器的單元測試,不是嗎? ( SlimerJS項目提供了類似的功能:運行無頭Gecko渲染工具包來測試Firefox瀏覽器中發生的頁面渲染。)
現在,您已經是一位經驗豐富的MEAN開發人員,您已經非常熟悉如何從瀏覽器中拔出組件并無頭運行它們:Node.js是Google Chrome的無頭腳本腳本引擎(V8)。 運行無頭渲染套件進行測試時,您應該感到賓至如歸。
回顧karma.conf.js,您可以看到PhantomJS在browsers數組中。 現在,您了解了如何在沒有看到GUI啟動的情況下在Jasmine客戶端測試中運行和通過所有瀏覽器。
配置業力以啟動其他瀏覽器
業力為所有主要瀏覽器提供啟動器。 如果您回頭查看package.json的devDependencies塊,可以看到已經為Firefox和Chrome安裝了啟動器。 如果您在計算機上安裝了這些瀏覽器,則將它們添加到karma.conf.js中的browsers陣列,然后鍵入grunt test以在新添加的瀏覽器中運行測試套件。
我鼓勵您訪問npm網站并搜索karma launcher以查看所有受支持的瀏覽器的列表。 您安裝每個啟動器,然后通過鍵入npm install karma- xxx -launcher --save-dev將其添加到package.json中。 安裝啟動程序后,將其添加到karma.conf.js中的browsers數組中,然后重新運行測試。
捕獲無法啟動的瀏覽器
Karma啟動器通常用于啟動位于同一臺計算機上的瀏覽器。 回想一下,Karma還可以用于在遠程瀏覽器上運行測試-例如智能手機,平板電腦和智能電視。 Karma可以捕獲任何支持Web套接字的瀏覽器,并將其用作測試目標。
要捕獲遠程瀏覽器,必須首先在測試運行之間使Karma服務器保持運行狀態。 要使Karma服務器永久運行,請在singleRun值更改為false :
// Continuous Integration mode // If true, it capture browsers, run tests and exit singleRun: true如果您重新啟動Karma服務器或任何捕獲的瀏覽器,它們將嘗試重新連接并重新運行所有測試。
既然Karma服務器已經啟動并正在運行,請在遠程瀏覽器中通過URL http:// your.server.ip.address :9876訪問它。 這就是使用Karma捕獲無法啟動的瀏覽器所需要的全部。
添加其他Karma記者
現在您可以輕松添加其他測試和瀏覽器,請考慮添加其他報告程序以捕獲并顯示測試結果。
首先,將dots報告程序添加到karma.conf.js中的reporters數組中。 下次輸入grunt test ,您會看到一系列點在屏幕上飛舞-每個通過測試。
這些點很可愛,但短暫。 除非您看著屏幕正在運行,否則如何知道通過了多少測試? 也許安裝一個更耐用的記者是有必要的。
karma-html-reporter最有可能是您想要的。 如圖1中的示例所示,您將獲得每個測試的詳細口頭測試結果,格式為HTML。
圖1. karma-html-reporter生成karma-html-reporter
要安裝karma-html-reporter ,請鍵入npm install karma-html-reporter --save-dev 。 然后對其進行配置,如下所示編輯karma.conf.js:
reporters: ['progress', 'html'],htmlReporter: {outputDir: 'karma_html' },有關完整的配置選項集,請參見karma-html-reporter 軟件包詳細信息 。
如果您更喜歡原始XML輸出而不是精細HTML輸出,請考慮安裝karma-junit-reporter 。 要安裝它,請鍵入npm install karma-junit-reporter --save-dev 。 然后如項目站點所示在karma.conf.js中對其進行配置。
您在npm網站上鍵入了karma launcher ,以搜索其他啟動器。 您應該同樣容易鍵入karma reporter以查找其他業力報告程序。
顯示Karma和伊斯坦布爾的代碼覆蓋率
沒有顯示測試代碼覆蓋范圍,沒有完整的測試基礎架構。 以前的報告僅向您顯示通過和失敗的測試,而沒有向您顯示您忘記編寫的測試。 一個好的代碼覆蓋率工具可以逐行向您顯示單元測試已訪問了代碼庫的哪些部分,更重要的是,單元測試尚未訪問了哪些代碼行。
如果通過鍵入npm install karma-coverage --save-dev karma-coverage插件(使用istanbul庫),請輸入npm install karma-coverage --save-dev并根據說明進行配置,您將獲得一組漂亮的報告,顯示每行代碼在您的應用程序中,如圖2所示。
圖2.覆蓋率報告
綠線已被單元測試觸及,紅線是等待將來的單元測試的線。
模擬依賴
編寫良好的單元測試的標志是它們的獨立性。 他們絕不應該依賴實際的數據庫或對實時Web服務進行實際的HTTP調用。 值得慶幸的是,模擬這些依賴關系是一種運行時間已久的測試方法。
可以考慮使用AngularJS附帶的$httpBackend模擬服務,而不是在客戶端Jasmine測試中進行實際的Ajax調用。
可以考慮使用Mockgoose (它是Mongoose(和MongoDB)的純內存內置替代品,專門用于測試目的),而不是依賴于實際的MongoDB數據庫進行測試。
使用Protractor.js運行端到端測試
到目前為止,您一直在運行單元測試。 單元測試(顧名思義)是不依賴GUI的測試。 單元測試適用于代碼庫的非UI部分。
但是,如何測試典型用戶在使用您的應用程序時將執行的所有鍵入和單擊按鈕呢? 要測試這種行為,可以安裝Protractor.js。
量角器主頁上有完整的說明和示例。 這是簡短的版本:鍵入npm install protractor --save-dev來安裝庫。 接下來,編寫Jasmine測試,這些測試訪問特定的URL并與頁面上的特定組件進行交互。 清單4顯示了項目首頁上的Protractor測試示例。
清單4.量角器測試
describe('angularjs homepage todo list', function() {it('should add a todo', function() {browser.get('http://www.angularjs.org');element(by.model('todoText')).sendKeys('write a protractor test');element(by.css('[value="add"]')).click();var todoList = element.all(by.repeater('todo in todos'));expect(todoList.count()).toEqual(3);expect(todoList.get(2).getText()).toEqual('write a protractor test');}); });您可能已經todoText ,該測試將訪問AngularJS主頁,找到todoText元素,鍵入測試字符串,然后單擊添加按鈕。 然后,它將運行一系列斷言以確保出現期望值。
結論
就像我之前說的和我經常說的那樣,一個測試值得一千個意見。 但是厚臉皮的重新連接僅在您可以使用可靠的軟件實踐對其進行備份時才有效。 如果您將從本文中汲取的教訓放到適當的位置,那么您將步入“工程嚴謹”的道路,這是快速發展,不斷變化的軟件生態系統的一部分。
翻譯自: https://www.ibm.com/developerworks/opensource/library/wa-mean6/index.html
總結
- 上一篇: 架构一个数据交换与信息共享平台
- 下一篇: fcpx:专业视频降噪插件 ProDen