精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

編寫可測試的JavaScript代碼

移動開發
無論我們使用和Node配合在一起的測試框架,例如Mocha或者Jasmine,還是在像PhantomJS這樣的無頭瀏覽器中運行依賴于DOM的測試,和以前相比,我們有更好的方式來對JavaScript進行單元測試。

無論我們使用和Node配合在一起的測試框架,例如Mocha或者Jasmine,還是在像PhantomJS這樣的無頭瀏覽器中運行依賴于DOM的測試,和以前相比,我們有更好的方式來對JavaScript進行單元測試。

然而,這并不意味著我們要測試的代碼就像我們的工具那樣容易!組織和編寫易于測試的代碼需要花費一些精力和并對其進行規劃,但是在函數式編程的啟發下,我們發現了一些模式,當我們需要測試我們的代碼時,這些模式可以幫助我們避免那些“坑”。在這篇文章中,我們會查看一些有用的小貼士和模式,來幫助我們在JavaScript中編寫可測試的代碼。

保持業務邏輯和顯示邏輯分離

對于基于JavaScript的瀏覽器應用程序來說,其中一項主要工作就是監聽終端用戶觸發的DOM事件,然后通過運行一些業務邏輯并在頁面上顯示結果,以此對用戶做出反饋。在建立DOM事件監聽器的地方,有時會誘惑你編寫一個匿名函數來完成所有這些工作。這樣帶來的問題是為了測試匿名函數,你不得不去模擬DOM事件。這樣不僅會增加代碼行數,而且會增加測試運行的時間。 

 

 

 

與之相反,編寫一個有名字的函數,然后將其傳給事件處理器。通過這種方式,你可以直接針對這個有名字的函數編寫測試用例,而不用去觸發一個假的DOM事件。

這不僅僅可以應用到DOM上。在瀏覽器和Node上的很多API,都被設計成觸發和監聽事件,或者等待其它類型的異步工作完成。憑經驗說,如果你編寫了大量的匿名回調函數,那么你的代碼可能不會容易被測試。

  1. // hard to test 
  2. $('button').on('click', () => { 
  3.     $.getJSON('/path/to/data'
  4.         .then(data => { 
  5.             $('#my-list').html('results: ' + data.join(', ')); 
  6.         }); 
  7. }); 
  8.   
  9. // testable; we can directly run fetchThings to see if it 
  10. // makes an AJAX request without having to trigger DOM 
  11. // events, and we can run showThings directly to see that it 
  12. // displays data in the DOM without doing an AJAX request 
  13. $('button').on('click', () => fetchThings(showThings)); 
  14.   
  15. function fetchThings(callback) { 
  16.     $.getJSON('/path/to/data').then(callback); 
  17.   
  18. function showThings(data) { 
  19.     $('#my-list').html('results: ' + data.join(', ')); 
  20.  

對異步代碼使用回調或者Promise

在上述的示例代碼中,我們經過重構的函數fetchThings會運行一個AJAX請求,以異步的方式完成了大部分工作。這意味著我們不能運行函數并測試它是否按照我們預期的那樣運行,因為我們不知道它什么時候運行完。

解決這個問題最常見的方法,是向函數中傳遞一個回調函數作為參數,作為異步調用。這樣,在你的單元測試中,你可以在傳遞的回調函數中運行一些斷言。 

 

 

 

另外一種常見并且越來越流行的組織異步代碼方法,是使用Promise API的方式。幸運的是,$.ajax和其它大部分jQuery的異步函數已經返回了Promise對象,因此它已經涵蓋了大部分常見的用例。

  1. // 很難測試;我們不知道AJAX請求會運行多長時間 
  2.   
  3. function fetchData() { 
  4.     $.ajax({ url: '/path/to/data' }); 
  5.   
  6. //可測試的;我們傳入一個回調函數,然后在其中運行斷言 
  7.   
  8. function fetchDataWithCallback(callback) { 
  9.     $.ajax({ 
  10.         url: '/path/to/data'
  11.         success: callback, 
  12.     }); 
  13.   
  14. //同樣可測試的:在返回的Promise解析完后,我們可以運行斷言 
  15.   
  16. function fetchDataWithPromise() { 
  17.     return $.ajax({ url: '/path/to/data' }); 
  18.  

避免副作用

要編寫那些使用參數并且返回值僅僅依賴那些參數的函數,就像將數字傳入數學公式,然后取得結果。如果你的函數依賴于一些外部的狀態(例如類實例的屬性或者某些文件的內容),那么你在測試這個函數之前,就不得不去設置一些狀態,在測試用例中需要更多的設置。你不得不去認為那些正在運行的代碼不會修改同一個的狀態。 

 

 

 

同樣,你需要避免編寫那些會修改外部狀態的函數,例如向文件寫入內容或者向數據庫保存數據。這會避免一些副作用,來影響你測試其他代碼的能力。一般來說,***是將副作用和代碼控制在一起,讓“表面積”盡可能小。對于類和對象實例來說,類方法的副作用應該被限制在被測試的類實例的范圍內。

  1. // 很難測試;我們不得不設置一個globalListOfCars對象和一個名為#list-of-models的DOM結構,然后才能測試這段代碼 
  2.   
  3. function processCarData() { 
  4.     const models = globalListOfCars.map(car => car.model); 
  5.     $('#list-of-models').html(models.join(', ')); 
  6.   
  7. // 容易測試;我們傳遞一個參數然后測試它的返回值,而不需要設置任何全局變量或者檢查任何DOM結果 
  8.   
  9. function buildModelsString(cars) { 
  10.     const models = cars.map(car => car.model); 
  11.     return models.join(','); 
  12.  

使用依賴注入

在函數中,有一種通用的模式,可以用來降低對外部狀態的使用,這就是依賴注入 —— 將函數的所有外部需要都通過函數參數的方式傳遞給函數。

  1. // 依賴于一個外部狀態數據連接實例;很難測試 
  2.   
  3. function updateRow(rowId, data) { 
  4.     myGlobalDatabaseConnector.update(rowId, data); 
  5.   
  6. // 將數據庫連接實例作為參數傳遞給函數;很容易測試。 
  7.   
  8. function updateRow(rowId, data, databaseConnector) { 
  9.     databaseConnector.update(rowId, data); 
  10.  

使用依賴注入的一個主要好處,是你可以在單元測試中傳入mock對象,這樣就不會導致真的副作用(在這個例子中,就是更新數據庫行),你只需要斷言你的mock對象是按照期望的方式運行即可。

為每一個函數設置一個唯一的目的

將長函數分解成一系列小的、單一職責的函數。這樣我們可以更容易的去測試每一個函數是否是正確的,而不再希望一個大函數在返回結果之前就正確的做了所有的事情。

在函數式編程中,將幾個單一職責的函數拼在一起的行為稱作“組合”。Underscore.js甚至有一個名為_.compose的函數,它將一個函數列表中的函數串在一起,將每一函數的返回結果作為輸入傳遞給下一個函數。

  1. // 很難測試 
  2.   
  3. function createGreeting(name, location, age) { 
  4.     let greeting; 
  5.     if (location === 'Mexico') { 
  6.         greeting = '!Hola'
  7.     } else { 
  8.         greeting = 'Hello'
  9.     } 
  10.   
  11.     greeting += ' ' + name.toUpperCase() + '! '
  12.   
  13.     greeting += 'You are ' + age + ' years old.'
  14.   
  15.     return greeting; 
  16.   
  17. // 很容易測試 
  18.   
  19. function getBeginning(location) { 
  20.     if (location === 'Mexico') { 
  21.         return '¡Hola'
  22.     } else { 
  23.         return 'Hello'
  24.     } 
  25.   
  26. function getMiddle(name) { 
  27.     return ' ' + name.toUpperCase() + '! '
  28.   
  29. function getEnd(age) { 
  30.     return 'You are ' + age + ' years old.'
  31.   
  32. function createGreeting(name, location, age) { 
  33.     return getBeginning(location) + getMiddle(name) + getEnd(age); 
  34.  

不要改變參數

在JavaScript中,數組和對象傳遞的是引用,而非值,因此它們是可變的。這意味著當你將對象或者數組作為參數傳遞給函數時,你的代碼和使用你傳遞的對象或數組的函數,都有能力去修改內存中同一個數組或者對象。這意味著當你測試你自己的代碼時,你必須信任所有你調用的函數中,沒有任何函數會修改你的對象。每當你添加一些新的可以修改同一個對象的代碼時,跟蹤對象應該是什么樣子就會變得越來越困難,從而更難去測試它們。 

 

 

[[177541]] 

相反,當你有一個函數需要使用對象或者數組時,你應該在代碼中對待對象或者數組就像它們是只讀的。你可以根據需要創建新的對象或者數組,然后對齊填充?;蛘?,使用Undersocre或者Lodash去對傳入的對象或者數組做一個拷貝,然后再對齊進行操作。更好的選擇是,使用一些像Immutable.js這樣的工具,去創建只讀的數據結構。

  1. // 修改了傳入的對象 
  2.   
  3. function upperCaseLocation(customerInfo) { 
  4.     customerInfo.location = customerInfo.location.toUpperCase(); 
  5.     return customerInfo; 
  6.   
  7. // 返回了一個新的對象 
  8.   
  9. function upperCaseLocation(customerInfo) { 
  10.     return { 
  11.         name: customerInfo.name
  12.         location: customerInfo.location.toUpperCase(), 
  13.         age: customerInfo.age 
  14.     }; 
  15.  

在編碼之前先寫測試

在編碼之前先寫單元測試的過程被稱作測試驅動開發(TDD)。大量的開發者發現TDD非常有用。

通過先編寫測試用例,你就強迫自己從使用你代碼的開發者角度來考慮你要暴露的API,它還幫助你確保你只會編寫足夠的代碼來滿足測試用例的要求,而不要對解決方案“過度施工”,從而帶來不必要的復雜性。

在實踐中,TDD作為一條紀律,要覆蓋所有的代碼改動可能會比較困難。但是當它看上去值得嘗試的時候,這就是一個很好的方式來保證你的所有代碼都是可測試的。

總結

在編寫和測試復雜的JavaScript應用的時候,我們都知道有一些很容易遇到的“陷阱”,但我希望通過這些貼士和提醒,可以讓我們的代碼盡量簡單和函數化,我們可以做到讓測試覆蓋率很高,讓整體的代碼復雜性很低!

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2013-04-15 09:02:43

JavaScriptJS

2012-12-17 13:51:22

Web前端JavaScriptJS

2022-06-07 09:30:35

JavaScript變量名參數

2014-04-21 10:14:52

PromisesJavaScript

2009-06-24 15:00:39

Javascript代

2023-01-27 14:53:03

2011-11-23 09:06:00

2011-03-04 10:11:09

JavascriptAPI

2021-10-10 23:02:49

Golang語言代碼

2018-11-08 15:50:18

前端Javascript重用性

2011-12-29 15:02:27

JavaScript

2022-06-21 12:27:12

JavaScript前端

2022-08-02 10:33:11

JavaScript代碼

2024-01-30 08:54:05

JavaScript技巧代碼

2023-09-11 11:05:49

軟件開發TDD

2012-09-17 10:35:41

JavaScriptJS代碼

2025-06-11 03:22:00

JavaScript開發前端

2015-08-27 13:11:18

JavaScript代碼

2022-08-28 19:03:18

JavaScript編程語言開發

2022-05-10 10:28:21

JavaScript代碼
點贊
收藏

51CTO技術棧公眾號

久久手机在线视频| 三级全黄做爰视频| 中文字幕在线三区| 国产成人av电影在线播放| 欧美精品福利视频| 高清一区在线观看| 国产性猛交96| 日韩精品99| 亚洲欧洲韩国日本视频| 国产精品久久国产精品| 久久久久久少妇| 精品午夜福利在线观看| 日本www在线观看视频| 国产成人精品免费一区二区| 欧美亚洲第一区| 国产suv精品一区二区68| 精品久久ai| 欧美精品在线视频| 久久久久狠狠高潮亚洲精品| av激情在线| 久久久精品2019中文字幕之3| 91美女片黄在线观看游戏| 一级片中文字幕| 久久久久久免费视频| 亚洲久久久久久久久久| 精人妻一区二区三区| 国产精品天堂蜜av在线播放 | 狠狠久久亚洲欧美专区| 91免费视频黄| www.av在线播放| 2021久久国产精品不只是精品| 亚洲free性xxxx护士hd| 黄色av网站免费| 国产伦理一区| 97在线视频观看| 久草视频中文在线| 欧美精品日本| 欧美 日韩 国产 成人 在线 91| 欧美激情 亚洲a∨综合| 亚洲午夜精品久久久久久性色 | 色综合888| 国产乱码精品| 欧美精品成人在线| 久久久久亚洲av成人片| 亚洲中无吗在线| 日韩在线视频免费观看高清中文| 97人妻天天摸天天爽天天| 懂色av一区二区| 日韩三级视频在线看| 一区二区三区四区毛片| 日韩一区二区三区免费视频| 欧美日韩中文字幕日韩欧美| 国产精品国产亚洲精品看不卡| 97caopron在线视频| 亚洲天堂2016| 美女在线免费视频| 国内外激情在线| 中文字幕一区二区日韩精品绯色| 一区二区不卡在线观看| 日本欧美在线视频免费观看| 国产精品欧美综合在线| 亚洲人成网站在线观看播放| 尤物网在线观看| 国产精品不卡在线| 日本一道在线观看| 欧美hdxxx| 天天色 色综合| 人妻有码中文字幕| 日本肉肉一区 | 欧美大秀在线观看| 久久亚洲av午夜福利精品一区| 欧美三级在线| 97色在线观看| 黄色片视频免费| 美女视频一区二区| 亚洲最大的网站| 无套内谢的新婚少妇国语播放| 久久综合久久综合久久| 欧洲视频一区二区三区| 在线观看免费黄色| 一区二区三区欧美亚洲| 男人日女人下面视频| 日韩中文影院| 欧美肥胖老妇做爰| 久久性爱视频网站| 中文字幕av一区二区三区人| 中文字幕一区二区精品| www.毛片com| 国产精品日本| 国产美女精品免费电影| 成人1区2区3区| 久久亚洲精精品中文字幕早川悠里 | 国产欧美精品一区二区三区四区 | 国产真实乱人偷精品人妻| 少妇精品久久久一区二区三区 | yellow在线观看网址| 色哟哟国产精品| √天堂资源在线| 欧美日韩一区二区三区不卡视频| 在线观看日韩欧美| 久久久久久久九九九九| 久久久久久网| 俄罗斯精品一区二区三区| 黄色软件在线观看| 夜夜夜精品看看| 久久九九国产视频| 国产精品色在线网站| 中文字幕日韩av综合精品| 久久午夜无码鲁丝片午夜精品| 日韩不卡在线观看日韩不卡视频| 2019国产精品视频| 91社区在线| 精品毛片网大全| 想看黄色一级片| 国产成人久久| 午夜精品三级视频福利| 国产一区二区三区四区视频| 26uuu国产电影一区二区| www.黄色网址.com| 一区二区三区视频网站| 国产精品乡下勾搭老头1| 久久资源亚洲| 欧美高清另类hdvideosexjaⅴ| 日本道在线观看一区二区| 一区二区三区人妻| 日韩免费av| 538国产精品一区二区免费视频 | 国产亚洲福利社区| 麻豆传媒视频在线观看免费| 色先锋资源久久综合| 国产情侣久久久久aⅴ免费| 国产精品久久久久久久久妇女| 欧美一级在线亚洲天堂| 国产91久久久| 亚洲精品国产视频| 日本中文字幕影院| 日韩电影免费网站| 国产精品精品久久久| 色婷婷中文字幕| 亚洲高清久久久| 在线成人精品视频| 欧美一区综合| 91精品国产一区二区三区动漫| 日韩黄色影院| 欧美日韩国产一级| 天堂网中文在线观看| 日本欧美加勒比视频| 日韩精品电影网站| 欧美在线va视频| 国产亚洲欧美日韩一区二区| 免费av网站在线| wwww国产精品欧美| 欧美三级午夜理伦三级| 亚洲资源网站| 国产精品久久久久久av福利软件| 精品999视频| 欧美在线观看视频一区二区| 精品欧美一区二区久久久| 日韩av在线发布| 亚洲精品欧洲精品| 日韩国产一二三区| 综合国产在线观看| 国产精品色综合| 亚洲精品视频免费看| 性感美女一区二区三区| 9国产精品视频| 欧美凹凸一区二区三区视频| 免费电影日韩网站| 在线观看久久久久久| 一区二区三区精彩视频| 亚洲免费成人av| 给我免费观看片在线电影的| 男女精品网站| 亚洲一区二区三区免费看| 免费精品一区| 国内久久久精品| 国产原创av在线| 8v天堂国产在线一区二区| 青青青在线视频| 91年精品国产| 天天操天天摸天天爽| 91精品综合久久久久久久久久久| 91在线看网站| 一区二区三区短视频| 一区国产精品视频| 国内精品久久久久久久久久| 亚洲444eee在线观看| av网站免费在线看| 国产一区二区三区四区五区入口| 国产成人一区二区三区别| 曰本一区二区三区视频| 成人在线视频网站| 18video性欧美19sex高清| 伊人男人综合视频网| 亚洲av无码乱码在线观看性色| 欧美日韩国产精品一区二区不卡中文| 欧美亚洲色综久久精品国产| 风间由美一区二区三区在线观看| 青青在线视频观看| 欧美三区不卡| 亚洲欧美国产精品桃花| 国产精品玖玖玖在线资源| 国产日韩精品视频| 欲香欲色天天天综合和网| 久久精品小视频| 国产精品国产高清国产| 91精品国产手机| 中文字幕av影院| 亚洲综合图片区| 国产精品综合激情| 99免费精品视频| 真实乱偷全部视频| 美美哒免费高清在线观看视频一区二区| 精品国偷自产一区二区三区| 欧美gayvideo| 日韩精品无码一区二区三区| a级日韩大片| 亚洲自拍偷拍一区| 福利视频亚洲| 日韩免费观看视频| 国产白丝在线观看| 久久综合五月天| 91九色在线porn| 亚洲欧洲视频在线| 天堂成人在线观看| 日韩一级视频免费观看在线| 夜夜狠狠擅视频| 日韩欧美在线第一页| 国产五月天婷婷| 亚洲精品伦理在线| 一区二区三区影视| 国产精品久久久久久久久快鸭| 美女被到爽高潮视频| 91视频在线观看免费| 色婷婷免费视频| 成人午夜精品在线| 国产免费a级片| 国产黄人亚洲片| 国产毛片久久久久久| 久久99国产精品免费| 国产精品一区二区羞羞答答| 麻豆精品网站| 亚洲国产精品久久久久爰色欲| 99人久久精品视频最新地址| 老子影院午夜伦不卡大全| 国内成人在线| 国产xxxx振车| 亚洲理伦在线| 一区二区传媒有限公司| 中文日韩在线| 欧美 日韩 国产一区| 免费在线亚洲欧美| 成年人小视频网站| 日本怡春院一区二区| 亚洲黄色小视频在线观看| 麻豆精品国产91久久久久久| 亚洲一级免费在线观看| 久久国内精品自在自线400部| 污色网站在线观看| 国产主播一区二区| 97超碰免费在线观看| 国产成人精品1024| 国产xxxx视频| 久久精品日韩一区二区三区| www色com| 一区二区三区中文在线观看| 国产一级片播放| 狠狠躁天天躁日日躁欧美| 日本中文字幕在线观看视频| 欧美日韩中文国产| 99精品人妻无码专区在线视频区| 日韩你懂的在线观看| 亚洲aⅴ在线观看| 中文综合在线观看| 黄色美女视频在线观看| 欧美一级bbbbb性bbbb喷潮片| 亚洲欧洲美洲av| 91精品久久久久久久久中文字幕| 一区二区日韩| 欧美一区二区三区电影在线观看| 日韩系列欧美系列| 久操网在线观看| 秋霞电影网一区二区| 手机在线免费毛片| 91麻豆6部合集magnet| 午夜影院黄色片| 一个色综合av| 免费在线不卡av| 欧美va亚洲va在线观看蝴蝶网| 无码精品在线观看| www日韩中文字幕在线看| 爱看av在线| 国产欧美va欧美va香蕉在| 超碰在线一区| 亚洲欧美精品| 亚洲神马久久| 91亚洲一区二区| 91免费看片在线观看| 糖心vlog免费在线观看| 欧美日韩在线一区| 国产99对白在线播放| 国产午夜精品一区理论片飘花 | 亚洲三级视频在线观看| 国产剧情在线视频| 日韩视频123| a√资源在线| 欧美野外猛男的大粗鳮| 亚洲一区二区三区四区电影| 亚洲精品免费在线看| 99精品久久久| 无码人妻丰满熟妇区毛片蜜桃精品| 国产网站一区二区| 国产一级淫片免费| 91麻豆精品国产91久久久久久久久| 男女视频在线观看免费| 久久久久久久久国产| 国产亚洲人成a在线v网站| 久久久福利视频| 欧美久久综合| 在线观看免费视频高清游戏推荐| 91女厕偷拍女厕偷拍高清| 美女毛片在线观看| 欧美一区二区三区四区高清 | 色妞ww精品视频7777| 性欧美精品一区二区三区在线播放| 亚洲精选成人| 折磨小男生性器羞耻的故事| 亚洲你懂的在线视频| 亚洲一区二区人妻| 亚洲网站在线播放| 69久成人做爰电影| 乱一区二区三区在线播放| 9色精品在线| 久久久老熟女一区二区三区91| 亚洲另类在线制服丝袜| 国产精品免费无遮挡| 中文日韩在线视频| 99久久婷婷国产综合精品首页| 久久久久se| 久久成人精品| 强伦人妻一区二区三区| 欧美日韩午夜剧场| 欧美日韩在线精品一区二区三区激情综 | 高清免费日韩| 国户精品久久久久久久久久久不卡| 五月天六月丁香| 亚洲精品欧美专区| www.av导航| 欧美黑人视频一区| silk一区二区三区精品视频| www.国产在线视频| 国产寡妇亲子伦一区二区| 精品欧美一区二区久久久久| 日韩一区二区在线播放| 欧美aaa免费| 国内精品久久国产| 男女精品网站| 娇小11一12╳yⅹ╳毛片| 91麻豆精品国产91| h片在线观看网站| 国产精品美女久久久久av福利| 亚洲国产高清视频| 深爱五月激情网| 欧美在线免费观看视频| aaa在线观看| 444亚洲人体| 日韩网站在线| 亚洲自拍偷拍图| 91精品国产综合久久香蕉的特点| av中文字幕在线观看| 国内视频一区| 天堂一区二区在线免费观看| 日本一区二区视频在线播放| 欧美日韩1234| 成人影院在线播放| 欧美自拍资源在线| 精品亚洲国内自在自线福利| 久久久久久福利| 亚洲精品一区二区在线| 色综合视频一区二区三区日韩 | 日韩一区二区三区视频在线观看 | 午夜精品成人在线| 美丽的姑娘在线观看免费动漫| 国产精品视频白浆免费视频| 一区二区三区四区电影| 日批在线观看视频| 欧洲激情一区二区| 亚洲图区一区| 欧美一区1区三区3区公司| 极品少妇xxxx精品少妇偷拍| 精品在线视频免费| 中文字幕久久久av一区| 亚洲性视频在线| 午夜精品久久久内射近拍高清| 亚洲蜜臀av乱码久久精品| 偷拍自拍在线视频| 91在线视频成人| 视频一区中文字幕国产| 欧美国产在线看| 中文字幕欧美专区|