前言
筆者多年來一直在微軟公司從事與Web開發相關的技術工作,幫助客戶維護和處理各種Web應用的突發事件,期間走訪了大量客戶,為他們提供解決方案或指導意見。我們深深感受到近些年來Web技術的快速發展對Web開發人員、測試人員帶來的諸多挑戰:
●Web開發是一個開放的、不斷演進的、高速迭代的領域。即便是過去一直被詬病為封閉的微軟公司也開始擁抱開源世界,提供.NETCore、TypeScript等多項開源和跨平臺技術。這對于過去長期在單一廠商平臺上進行項目開發的技術人員而言,就更需要積極主動地學習新技術,接受新挑戰,以適應變化,滿足業務需求!窕贘avaScript的前端應用規模越來越大,功能越來越復雜,前端測試已經成為保證產品質量的關鍵因素。同時,由于Web開發存在測試周期短、更新頻繁的特點,傳統測試人員需要具備一定的開發能力才能充分利用自動化測試工具來提高測試效率!耠S著敏捷軟件開發方法和DevOps的流行,測試和開發環節之間的界限逐漸變得模糊。傳統開發人員需要了解一定的測試方法并具有相應的思維方式,才能設計出良好的測試用例。由于測試和開發環節的融合,無論是開發人員還是測試人員都需要不斷提高自身的能力和價值。
本書是筆者在開發測試領域中的實踐與經驗的總結,希望讀者通過對本書的學習,能夠掌握Web前端測試的各種技巧,提升自己的能力,迎接新技術的挑戰。
本書內容
全書共分四個部分,前兩部分為金鑫編寫,后兩部分為武帥編寫。
●第一部分為基礎篇(第1~2章),總覽了前端開發測試中的挑戰與進行測試轉型的方法,以及基于Node.js搭建測試開發基礎環境的步驟!竦诙糠譃閱卧獪y試篇(第3~7章),基于單元測試理論深入剖析了Jasmine測試框架的結構與各種使用范式,內容覆蓋了所有主流單元測試的技巧。然后,結合
gulp、Karma等構建、執行工具對單元測試進行自動化處理。最后以實戰的形式演示了AngularJS單元測試最佳實踐以及Istanbul代碼覆蓋率的應用等內容。
●第三部分為自動化測試篇(第8~14章),由淺入深地介紹了Selenium各個組件的功能特點和WebDriver在自動化測試中的使用技巧。進而基于Protractor深入介紹了在Node.js環境下,通過JavaScript代碼結合WebDriver進行自動化測試,并全面覆蓋Chrome、Firefox、IE和Edge等主流瀏覽器的最佳實踐,內容包括頁面對象模型、性能測試、數據驅動測試和分布式測試等。●第四部分為集成篇(第15~16章),闡述了基于持續集成技術來實現更快、更可靠的軟件交付方法,比較了當前主流CI系統的特點,展示了通過Jenkins與TFS、VSTS和GitHub集成來實現Web應用持續測試的方法。本書適合對象
本書適合所有Web開發人員、測試人員和項目經理做學習、參考之用。本書涉及的示例代碼,讀者可從網址https://github.com/FrontEndTesting/webtesting-book-demo處下載,供對照學習。
致謝
首先,感謝家人對我們利用業余時間編寫本書的理解,在漫長的編寫過程中始終給予關愛和支持。其次,感謝張量、毛蔚、徐春林和顧潔等微軟公司同事的大力鼓勵與支持,本書的成書與他們密不可分。
由于筆者學識有限,時間倉促,書中難免出現錯誤或疏漏,懇請廣大讀者不吝指正。如果您有什么寶貴意見,請發送郵件至jin_xin2000@outlook.com,我們將不勝感激。
金鑫,微軟專家級工程師,目前和微軟平臺即服務產品(PaaS)Azure App Service的產品組合作,為微軟Azure App Service的支持工程師提供技術咨詢、解決方案和自動化診斷工具。自2000年加入微軟亞太區全球技術支持中心以來一直專注于企業級Web應用和分布式系統,精通IIS,ASP.NET,Windows Workflow Foundation, COM+ 等技術。最近幾年致力于現代Web開發技術和云計算,包括開源的AngularJS, TypeScript以及Azure App Service。 武帥,微軟專家級支持工程師。于2011年加入微軟后一直專注于企業級應用的開發與技術咨詢工作,精通ASP.NET MVC, Entity Framework和AngularJS等Web前端技術。目前主要致力于微軟公有云Azure、Visual Studio Team Service、Xamarin和.NET Core等新興技術的開發咨詢與推廣。
第1章前端開發測試總覽...2
1.1Web技術的發展和挑戰...2
1.2傳統開發流程的局限性...4
1.3傳統手工測試的局限性...6
1.4開發模式的轉型...7
1.4.1敏捷軟件開發...7
1.4.2全流程測試...9
1.4.3讓測試自動化...11
1.4.4持續集成...11
1.4.5DevOps...12
1.5本書目標...13
第2章搭建測試基礎環境...15
2.1JavaScript的運行環境Node.js...15
2.1.1什么是Node.js...15
2.1.2Node.js的版本發展...17
2.1.3安裝Node.js...18
2.2軟件包管理系統NodePackageManager(npm)...21
2.2.1安裝和更新npm...21
2.2.2package.json...22
2.2.3安裝軟件包...23
2.2.4列出已安裝的軟件包...27
2.3代碼編輯器(VisualStudioCode)...28
目錄
2.3.1安裝VisualStudioCode...28
2.3.2初識VisualStudioCode...29
單元測試篇
第3章單元測試概論...34
3.1單元測試的特性...34
3.2單元測試的重要性...35
3.3測試金字塔...37
3.4測試先行(Test-First)...8
3.4.1測試驅動開發(Test-DrivenDevelopment)...39
3.4.2行為驅動開發(Behavior-DrivenDevelopment)...40
3.5Web前端測試框架...42
第4章深入Jasmine單元測試...44
4.1初識Jasmine...44
4.1.1獲取Jasmine...44
4.1.2前端單元測試架構...46
4.1.3Jasmine測試框架類庫...46
4.2組織測試用例...48
4.2.1describe...48
4.2.2it...49
4.2.3安裝和拆卸...50
4.2.4禁用測試套件和掛起測試用例...54
4.3創建單元測試...55
4.3.1準備測試場景...55
4.3.2編寫測試用例...56
4.3.3執行測試......58
4.4Jasmine的斷言...59
4.4.1內置匹配器...59
4.4.2自定義匹配器(CustomMatcher)........................67
4.4.3自定義相等檢驗器(CustomEqualityTester)
..................68
4.4.4非對稱相等檢驗器(AsymmetricEqualityTester)...............70
4.4.5輔助匹配函數...71
4.5測試替身(TestDouble)...74
4.5.1測試替身的類型...74
4.5.2使用JasmineSpies......77
4.6測試異步代碼...84
4.6.1Jasmine的異步支持...87
4.6.2模擬JavaScriptTimeout相關函數...........................89
4.7Jasmine插件...90
4.7.1jasmine-ajax...90
4.7.2jasmine-jquery...94
4.8基于瀏覽器調試......100
第5章單元測試執行工具Karma..............................102
5.1初識Karma...102
5.2安裝Karma和相關插件...104
5.2.1安裝Karma...104
5.2.2安裝插件...105
5.3Karma的配置...106
5.3.1生成配置文件...106
5.3.2配置文件的說明......107
5.4基于Karma的調試...115
5.5前端自動化任務構建工具..............................116
5.5.1gulp和Grunt...116
5.5.2gulp的API...118
5.5.3運行gulp任務...122
5.6Karma和gulp集成...123
第6章AngularJS應用的單元測試...........................125
6.1測試AngularJS應用的挑戰..............................125
6.2初識ngMock...127
6.2.1準備測試環境...127
6.2.2理解模塊(Module)...128
6.2.3理解注入機制(Inject)
...131
6.3AngularJS單元測試最佳實踐...........................138
6.3.1測試Controller...138
6.3.2單元測試中的Scope...142
6.3.3測試HTTP交互...144
6.3.4測試Directive...154
6.3.5測試$timeout和$interval...166
6.3.6測試Promise...171
6.3.7測試$log......174
6.3.8測試$exceptionHandler...175
第7章代碼覆蓋率...177
7.1代碼覆蓋率的衡量標準...177
7.1.1函數覆蓋率(FunctionCoverage)........................177
7.1.2語句覆蓋率(StatementCoverage)
........................178
7.1.3分支覆蓋率(BranchCoverage)........................179
7.1.4條件覆蓋率(ConditionCoverage)........................179
7.2代碼覆蓋率的意義...179
7.3JavaScript代碼覆蓋率工具Istanbul........................180
7.3.1安裝Istanbul...181
7.3.2覆蓋率測試...181
7.3.3覆蓋率閾值...183
7.3.4忽略代碼...183
7.3.5Istanbul工作原理......184
7.4使用Karma生成覆蓋率報告...........................185
自動化測試篇
第8章走進自動化測試...188
8.1自動化測試的優勢...188
8.2自動化測試實施流程...189
8.3自動化測試轉型的適應性..............................190
8.4測試工具的選擇......192
第9章初識Selenium...194
9.1Selenium發展歷史...194
9.2Selenium工具套裝...196
9.2.1SeleniumRC...196
9.2.2SeleniumWebDriver...197
9.2.3SeleniumGrid...198
9.2.4SeleniumIDE...198
第10章SeleniumWebDriver與元素定位........................205
10.1搭建集成開發環境...205
10.2NUnit測試框架......207
10.3編寫測試用例...209
10.4使用工廠模式創建驅動對象...........................212
10.5定位頁面元素...214
10.5.1基于id定位...214
10.5.2基于Name定位...215
10.5.3基于ClassName定位...216
10.5.4基于TagName定位...217
10.5.5基于LinkText定位...217
10.5.6基于PartialLinkText定位...218
10.5.7基于CssSelector定位...219
10.5.8基于XPath定位......220
第11章基于WebDriver的Protractor測試框架..................227
11.1WebDriver的JavaScript綁定...........................227
11.1.1WebDriverJs與Protractor...228
11.1.2Protractor特點概述...229
11.1.3Protractor的兼容性...230
11.2搭建Protractor測試環境...230
11.2.1安裝Protractor編輯器擴展..............................230
11.2.2準備AngularJS被測網站...231
11.2.3全局安裝Protractor與瀏覽器驅動........................234
11.2.4本地安裝Protractor與瀏覽器驅動........................235
11.2.5編寫測試代碼...235
11.2.6編寫配置文件...236
11.2.7運行測試用例...236
11.2.8調試......237
11.3選擇JavaScript測試框架..............................240
11.3.1配置JavaScript測試框架...240
11.3.2JavaScript測試框架的適配器...241
11.4定位頁面元素...244
11.4.1基于binding定位......245
11.4.2基于model定位......246
11.4.3基于options定位......246
11.4.4基于buttonText定位...247
11.4.5基于repeater定位...247
11.4.6基于js定位...248
11.4.7鏈式調用定位操作...249
11.4.8使用$和$$...250
11.4.9自定義定位策略......251
11.5異步流程控制...252
11.5.1使用Promise...253
11.5.2定制的ControlFlow...256
11.5.3JavaScript測試框架的異步適配器........................259
11.6頁面交互...260
11.6.1操作瀏覽器...260
11.6.2操作元素...263
11.7Protractor的等待機制...265
11.7.1waitForAngular...265
11.7.2使用sleep...266
11.7.3隱式等待...266
11.7.4顯式等待...267
11.8測試非AngularJS程序...269
第12章使用SeleniumServer...273
12.1SeleniumServer環境配置..............................273
12.1.1安裝JavaJDK...274
12.1.2下載SeleniumServerStandalone........................275
12.1.3下載瀏覽器驅動......276
12.1.4配置Protractor...276
12.1.5啟動SeleniumServer...277
12.2JSONWireProtocol與W3CWebDriver標準..................279
12.3Selenium3.0...282
12.4配置瀏覽器...282
12.4.1Chrome......285
12.4.2Firefox......285
12.4.3Edge......288
12.4.4IE.........289
12.4.5多瀏覽器測試...291
第13章自動化測試最佳實踐...294
13.1頁面對象模型...294
13.1.1關注點分離...295
13.1.2實現Protractor頁面對象...296
13.1.3頁面對象最佳實踐...306
13.2數據驅動測試...307
13.3測試報告...311
13.3.1控制臺報告...312
13.3.2JUnit報告...313
13.3.3HTML報告...315
13.4性能測試...316
13.5圖像匹配...319
13.6任務自動化...322
13.6.1與gulp集成...322
13.6.2npm腳本...325
第14章分布式自動化測試...327
14.1分布式測試概述...327
14.2基于SeleniumGrid的分布式測試........................328
14.2.1啟動中央節點...329
14.2.2注冊工作節點...329
14.2.3執行測試...331
14.3基于云計算的分布式測試...........................333
14.4配置共享...336
集成篇
第15章持續集成概論...340
15.1開發流程自動化...340
15.1.1什么是持續集成......341
15.1.2持續集成的價值......341
15.2持續集成的功能特征...343
15.2.1編譯......343
15.2.2測試......344
15.2.3審計......344
15.2.4部署......345
15.2.5反饋......345
15.3如何實施持續集成...345
15.3.1消除誤解...345
15.3.2前提條件...346
15.3.3CI工具......347
15.3.4實踐準則...348
15.4選擇持續集成工具...350
第16章持續測試......352
16.1測試策略...352
16.2基于Jenkins的持續集成...353
16.3集成TeamFoundationServer...........................356
16.3.1創建項目...356
16.3.2從VisualStudioCode提交變更...........................358
16.3.3配置TFS插件...359
16.3.4創建并配置Jenkins構建項..............................360
16.3.5集成單元測試...364
16.3.6集成自動化測試......368
16.3.7郵件反饋...370
16.4集成VisualStudioTeamServices........................371
16.5集成GitHub...376
16.5.1配置GitHub...377
16.5.2配置Jenkins...379
16.5.3配置構建任務...380
第1章前端開發測試總覽第2章搭建測試基礎環境
3第1章前端開發測試總覽和ASP等生成這樣的字符串。換句話說,所謂的“前端”是由后端服務器動態輸出而成的HTML網頁。在這樣的傳統Web應用中,前端只是充當一個展示層,服務調用、網頁跳轉流程等都需要由后端服務器處理。每當網頁功能有所變化時(即使網頁內容只有細微變動),瀏覽器都需要重新發起一個HTTP請求到服務器,然后由后端服務器重新生成整個頁面如圖1-1所示。這種方式不但增加服務器的負擔,降低響應速度,而且瀏覽器重復下載整個網頁會浪費網絡帶寬,對于移動應用很不經濟。服務器瀏覽器初始請求HTMLHTMLPageReloadFormPOST圖1-1傳統網頁生命周期而在現代Web應用中,當網頁的部分內容需要更新時,運行在瀏覽器內的JavaScript代碼通常會向服務器發送Ajax請求,而服務器端只需輸出必要的數據,不需要重新構造整個HTML頁面,如圖1-2所示。Web前端應用接收到來自服務器的數據后,只需重繪界面上需要變化的部分。這種方式提高了應用的響應速度,改善了用戶的使用體驗。同時,因為很多用戶交互的處理工作可以在瀏覽器內完成,無需向服務器發送HTTP請求,服務器和瀏覽器之間交換的數據量大幅減少,所以服務器負荷降低,響應速度也更快了。Web應用漸漸開始擁有和桌面應用一樣的響應速度和使用體驗。服務器瀏覽器初始請求HTMLJSONAjax{.}圖1-2現代單頁應用(SPA)生命周期除了網頁內容的更新,Web應用一部分業務邏輯的處理也從后端服務器慢慢移到前
端,Web前端開發變得越來越重要。而這一切都離不開JavaScript。
JavaScript是1995年由Netscape工程師BrendanEich花了10天的時間創造出來的,其最初目的是為了滿足用戶瀏覽網頁時產生的交互需求?梢哉f,JavaScript是為開發Web應用而誕生的。
自其誕生起的相當長一段時間內,這門在瀏覽器內執行一些簡單的校驗和互動的腳本語言常被稱之為“玩具語言”,堪稱世界上被人誤解最深的編程語言a。在簡潔的外表下,JavaScript其實有著強大的語言特性。它是一種面向對象的動態語言,包含類型、運算符、標準內置對象和方法。其語法來源于Java和C,所以這兩種語言的許多語法特性同樣適用于JavaScript。
隨著Web應用的普及,JavaScript自身也在不斷演化以適應更復雜的編程需求,目前JavaScript已經成為Web前端的實際標準,也是最熱門的編程語言之一。各種JavaScript前端框架,包括Ember、AngularJS、React和Vue等不斷涌現。
正因為基于JavaScript前端應用越來越重要,功能越來越復雜,對前端開發測試帶來了極大的挑戰。如何保證Web前端應用的正確性和可靠性成為了各大企業關注的問題。
●在市場需求的推動下,Web前端應用規模不斷擴大,一個應用可能有成千上萬行JavaScript代碼。這些代碼用于執行各種復雜的功能,為用戶提供不同的交互體驗。為了確保它們能實現預期的功能,因此Web前端應用測試的工作量也需要相應增加。●相對于傳統的桌面應用,用戶只要重新刷新瀏覽器就可以獲得最新版本的網頁,所以Web前端應用具有天生的快速迭代特征,可以頻繁地更新和發布。而激烈的商業競爭也使得Web前端應用開發周期縮短,對應的測試周期也非常短!癯薐avaScript代碼,Web前端應用還有各種超鏈接、表單以及圖片等信息,需要保證在不同的操作系統和瀏覽器上可以正確顯示網頁的內容。1.2傳統開發流程的局限性在過去二十年或更長的時間中,傳統的、非敏捷的瀑布式軟件開發模式通常依賴于一
aDouglasCrockford.JavaScript:TheWorld'sMostMisunderstoodProgrammingLanguage[OL].[2016].http://javascript.crockford.com/javascript.html.
第1章前端開發測試總覽
個嚴格的模式化開發流程。通常認為瀑布模型a是WinstonW.Royce在1970年提出的軟件開發模型(雖然他并沒有使用瀑布waterfall這個單詞)。這種方法源自傳統工業生產,嚴格遵循預先計劃的需求、分析、設計、編碼、測試和部署的步驟順序進行,每個步驟都有嚴格分工,由不同的技術人員分別執行。執行步驟的成果作為衡量進度的途徑,例如需求規格、設計文檔、測試計劃和代碼審閱等。但隨著各種新興技術的蓬勃發展,特別是在產品快速迭代的需求背景下,這種傳統開發流程的局限性日益明顯:
1.自由度低,缺乏靈活性傳統模式在項目早期即作出承諾,基于穩定的目標進行階段性的開發,這種方式自由度低,應對突發情況時缺乏靈活性。眾所周知,需求會隨著時間而變化,經常出現開發人員努力在設計前完成文檔,在編寫代碼前完成設計,最后卻因為需求有變化而不得不完全推倒重來的情況,不僅大量工作被浪費,甚至導致對后期需求的變化難以應變,代價高昂。
2.缺陷發現晚,無法及時反饋傳統流程一般在開發階段接近尾聲時才開始測試。雖然在這個階段進行測試相對容易,但是一些在早期的單元測試中可以輕易發現的缺陷可能要到最后階段才會發現,增加了被遺漏的風險。
由于缺陷發現得很晚,如果要解決問題,則有可能導致錯過發布的最后期限,再加上手工測試效率低下,任何一次代碼變更或缺陷修復對產品的影響都無法迅速反饋給開發人員。隨著發現的缺陷越來越多,開發人員只會對變更沒有信心,失去持續完善的動力。
3.協同合作缺失,容易引起團隊沖突傳統流程中每個步驟都有嚴格分工,不同階段的技術人員與上下游的工種往往溝通較少,甚至對產品本身的理解也存在差異。例如,開發人員和測試人員在思維和工作方式上的不同,使得他們對軟件需求和測試場景的表述發生歧義,從而引起雙方的溝通問題。而這些理解上的差異如果直到測試階段才被發現的話,則實在太晚,此時雙方的沖突與指責對解決問題沒有任何幫助。
4.產品質量無法保證傳統流程中常見的一個場景是在項目后期將要交付的階段,技術人員倉促地從開發環境構建轉為腳本配置,而長期在開發環境內依靠手工管理,構建腳本的時候就可能會遇到各種各樣的問題,例如接口沒有定義、配置文件丟失、組件不工作等。為了解決這些問
aWikipedia.Waterfallmodel[OL].[2016].https://en.wikipedia.org/wiki/Waterfall_model.
題,技術人員不得不把主要精力放在軟件構建上,結果時間成本越來越高,產品質量無法保證,甚至出現產品無法按時交付的情況。
1.3傳統手工測試的局限性軟件測試是在規定的條件下對程序進行操作,以發現程序中的錯誤,衡量軟件質量,并對其是否能滿足設計要求進行評估的過程。軟件測試的目的是希望以最小的代價盡可能多地找出軟件中潛在的錯誤和缺陷。
首先,測試人員會針對開發人員開發的功能寫出測試用例,例如表單應該填入的數據,頁面單擊順序,以及最后頁面期待的顯示效果。然后,測試人員會按照用例一步步進行手工檢驗,如果發現頁面行為異常,例如無法打開頁面或生成的數據不正確,則會在企業缺陷管理系統中提交缺陷記錄,供開發人員進行修正。在開發過程中,如果有新版本編譯出來,測試人員需要根據測試用例重新測試,確認是否有新缺陷,或者老缺陷是否已經得到了修正。
長久以來,這種傳統的手工測試模式在各大公司廣泛應用,并已被證明其能夠行之有效地保證產品質量。但伴隨著互聯網技術的發展,這種傳統的測試模式已經顯示出越來越多的瓶頸。
……