版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
使?Jest進(jìn)?React單元測(cè)試React單元測(cè)試?案前置知識(shí)為什么要進(jìn)?測(cè)試1.測(cè)試可以確保得到預(yù)期的結(jié)果2.作為現(xiàn)有代碼?為的描述3.促使開發(fā)者寫可測(cè)試的代碼,?般可測(cè)試的代碼可讀性也會(huì)??點(diǎn)4.如果依賴的組件有修改,受影響的組件能在測(cè)試中發(fā)現(xiàn)錯(cuò)誤測(cè)試類型單元測(cè)試:指的是以原件的單元為單位,對(duì)軟件進(jìn)?測(cè)試。單元可以是?個(gè)函數(shù),也可以是?個(gè)模塊或?個(gè)組件,基本特征就是只要輸?不變,必定返回同樣的輸出。?個(gè)軟件越容易些單元測(cè)試,就表明它的模塊化結(jié)構(gòu)越好,給模塊之間的耦合越弱。React的組件化和函數(shù)式編程,天?適合進(jìn)?單元測(cè)試功能測(cè)試:相當(dāng)于是?盒測(cè)試,測(cè)試者不了解程序的內(nèi)部情況,不需要具備編程語(yǔ)?的專門知識(shí),只知道程序的輸?、輸出和功能,從?戶的?度針對(duì)軟件界?、功能和外部結(jié)構(gòu)進(jìn)?測(cè)試,不考慮內(nèi)部的邏輯集成測(cè)試:在單元測(cè)試的基礎(chǔ)上,將所有模塊按照設(shè)計(jì)要求組裝成?系統(tǒng)或者系統(tǒng),進(jìn)?測(cè)試冒煙測(cè)試:在正式全?的測(cè)試之前,對(duì)主要功能進(jìn)?的與測(cè)試,確認(rèn)主要功能是否滿?需要,軟件是否能正常運(yùn)?開發(fā)模式:測(cè)試驅(qū)動(dòng)開發(fā),英?為TestingDrivenDevelopment,強(qiáng)調(diào)的是?種開發(fā)?式,以測(cè)試來(lái)驅(qū)動(dòng)整個(gè)項(xiàng)?,即先根據(jù)接?完成測(cè)試編寫,然后在完成功能是要不斷通過測(cè)試,最終?的是通過所有測(cè)試:?為驅(qū)動(dòng)測(cè)試,英?為BehaviorDrivenDevelopment,強(qiáng)調(diào)的是寫測(cè)試的風(fēng)格,即測(cè)試要寫的像?然語(yǔ)?,讓項(xiàng)?的各個(gè)成員甚?產(chǎn)品都能看懂測(cè)試,甚?編寫測(cè)試TDD和BDD有各?的使?場(chǎng)景,BDD?般偏向于系統(tǒng)功能和業(yè)務(wù)邏輯的?動(dòng)化測(cè)試設(shè)計(jì);?TDD在快速開發(fā)并測(cè)試功能模塊的過程中則更加?效,以快速完成開發(fā)為?的。技術(shù)選型:Jest+EnzymeJestJest是Facebook開源的?個(gè)前端測(cè)試框架,主要?于React和ReactNative的單元測(cè)試,已被集成在create-react-app中。Jest特點(diǎn):1.易?性:基于Jasmine,提供斷?庫(kù),?持多種測(cè)試風(fēng)格2.適應(yīng)性:Jest是模塊化、可擴(kuò)展和可配置的3.沙箱和快照:Jest內(nèi)置了JSDOM,能夠模擬瀏覽器環(huán)境,并且并?執(zhí)?4.快照測(cè)試:Jest能夠?qū)eact組件樹進(jìn)?序列化,?成對(duì)應(yīng)的字符串快照,通過?較字符串提供?性能的UI檢測(cè)5.Mock系統(tǒng):Jest實(shí)現(xiàn)了?個(gè)強(qiáng)?的Mock系統(tǒng),?持?動(dòng)和?動(dòng)mock6.?持異步代碼測(cè)試:?持Promise和async/await7.?動(dòng)?成靜態(tài)分析結(jié)果:內(nèi)置Istanbul,測(cè)試代碼覆蓋率,并?成對(duì)應(yīng)的報(bào)告EnzymeEnzyme是Airbnb開源的React測(cè)試?具庫(kù)庫(kù),它功能過對(duì)官?的測(cè)試?具庫(kù)ReactTestUtils的?次封裝,提供了?套簡(jiǎn)潔強(qiáng)?的API,并內(nèi)置Cheerio,實(shí)現(xiàn)了jQuery風(fēng)格的?式進(jìn)?DOM處理,開發(fā)體驗(yàn)?分友好。在開源社區(qū)有超???,同時(shí)也獲得了React官?的推薦。測(cè)試環(huán)境搭建安裝Jest、Enzyme,以及babel-jest。如果React的版本是15或者16,需要安裝對(duì)應(yīng)的enzyme-adapter-react-15和enzyme-adapter-react-16并配置。importEnzymefrom'enzyme';importAdapterfrom'enzyme-adapter-react-16';Enzyme.configure({adapter:newAdapter()});復(fù)制代碼在package.json中的script中增加"test:jest--config.jest.js".jest.js?件module.exports={setupFiles:['./test/setup.js',],moduleFileExtensions:['js','jsx',],testPathIgnorePatterns:['/node_modules/',],testRegex:'.*\\.test\\.js$',collectCoverage:false,collectCoverageFrom:['src/components/**/*.{js}',],moduleNameMapper:{"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":"<rootDir>/__mocks__/fileMock.js","\\.(css|less|scss)$":"<rootDir>/__mocks__/styleMock.js"},transform:{"^.+\\.js$":"babel-jest"},};復(fù)制代碼setupFiles:配置?件,在運(yùn)?測(cè)試案例代碼之前,Jest會(huì)先運(yùn)?這?的配置?件來(lái)初始化指定的測(cè)試環(huán)境moduleFileExtensions:代表?持加載的?件名testPathIgnorePatterns:?正則來(lái)匹配不?測(cè)試的?件testRegex:正則表?的測(cè)試?件,測(cè)試?件的格式為xxx.test.jscollectCoverage:是否?成測(cè)試覆蓋報(bào)告,如果開啟,會(huì)增加測(cè)試的時(shí)間collectCoverageFrom:?成測(cè)試覆蓋報(bào)告是檢測(cè)的覆蓋?件moduleNameMapper:代表需要被Mock的資源名稱transform:?babel-jest來(lái)編譯?件,?成ES6/7的語(yǔ)法JestAPIdescribe(name,fn):描述塊,講?組功能相關(guān)的測(cè)試?例組合在?起it(name,fn,timeout):別名test,?來(lái)放測(cè)試?例afterAll(fn,timeout):所有測(cè)試?例跑完以后執(zhí)?的?法beforeAll(fn,timeout):所有測(cè)試?例執(zhí)?之前執(zhí)?的?法afterEach(fn):在每個(gè)測(cè)試?例執(zhí)?完后執(zhí)?的?法beforeEach(fn):在每個(gè)測(cè)試?例執(zhí)?之前需要執(zhí)?的?法全局和describe都可以有上?四個(gè)周期函數(shù),describe的after函數(shù)優(yōu)先級(jí)要?于全局的after函數(shù),describe的before函數(shù)優(yōu)先級(jí)要低于全局的before函數(shù)beforeAll(()=>{console.log('globalbeforeall');});afterAll(()=>{console.log('globalafterall');});beforeEach(()=>{console.log('globalbeforeeach');});afterEach(()=>{console.log('globalaftereach');});describe('test1',()=>{beforeAll(()=>{console.log('test1beforeall');});afterAll(()=>{console.log('test1afterall');});beforeEach(()=>{console.log('test1beforeeach');});afterEach(()=>{console.log('test1aftereach');});it('testsum',()=>{expect(sum(2,3)).toEqual(5);});it('testmutil',()=>{expect(sum(2,3)).toEqual(7);});});復(fù)制代碼Jest擁有豐富的配置項(xiàng),可以寫在package.json?增加增加jest字段來(lái)進(jìn)?配置,或者通過命令?--config來(lái)指定配置?件。jest.fn(implementation):返回?個(gè)全新沒有使?過的mockfunction,這個(gè)function在被調(diào)?的時(shí)候會(huì)記錄很多和函數(shù)調(diào)?有關(guān)的信息jest.mock(moduleName,factory,options):?來(lái)mock?些模塊或者?件jest.spyOn(object,methodName):返回?個(gè)mockfunction,和jest.fn相似,但是能夠追蹤object[methodName]的調(diào)?信息,類似Sinon使?mock函數(shù)可以輕松的模擬代碼之間的依賴,可以通過fn或spyOn來(lái)mock某個(gè)具體的函數(shù);通過mock來(lái)模擬某個(gè)模塊。具體的API可以看。快照會(huì)?成?個(gè)組件的UI結(jié)構(gòu),并?字符串的形式存放在__snapshots__?件?,通過?較兩個(gè)字符串來(lái)判斷UI是否改變,因?yàn)槭亲址?較,所以性能很?。要使?快照功能,需要引?react-test-renderer庫(kù),使?其中的renderer?法,jest在執(zhí)?的時(shí)候如果發(fā)現(xiàn)toMatchSnapshot?法,會(huì)在同級(jí)?錄下?成?個(gè)__snapshots?件夾?來(lái)存放快照?件,以后每次測(cè)試的時(shí)候都會(huì)和第?次?成的快照進(jìn)??較。可以使?jest--updateSnapshot來(lái)更新快照?件。Jest?持對(duì)異步的測(cè)試,?持Promise和Async/Await兩種?式的異步測(cè)試。1.expect(value):要測(cè)試?個(gè)值進(jìn)?斷?的時(shí)候,要使?expect對(duì)值進(jìn)?包裹2.toBe(value):使?Object.is來(lái)進(jìn)??較,如果進(jìn)?浮點(diǎn)數(shù)的?較,要使?toBeCloseTo3.not:?來(lái)取反4.toEqual(value):?于對(duì)象的深?較5.toMatch(regexpOrString):?來(lái)檢查字符串是否匹配,可以是正則表達(dá)式或者字符串6.toContain(item):?來(lái)判斷item是否在?個(gè)數(shù)組中,也可以?于字符串的判斷7.toBeNull(value):只匹配null8.toBeUndefined(value):只匹配undefined9.toBeDefined(value):與toBeUndefined相反10.toBeTruthy(value):匹配任何使if語(yǔ)句為真的值11.toBeFalsy(value):匹配任何使if語(yǔ)句為假的值12.toBeGreaterThan(number):?于13.toBeGreaterThanOrEqual(number):?于等于14.toBeLessThan(number):?于15.toBeLessThanOrEqual(number):?于等于16.toBeInstanceOf(class):判斷是不是class的實(shí)例17.anything(value):匹配除了null和undefined以外的所有值18.resolves:?來(lái)取出promise為fulfilled時(shí)包裹的值,?持鏈?zhǔn)秸{(diào)?19.rejects:?來(lái)取出promise為rejected時(shí)包裹的值,?持鏈?zhǔn)秸{(diào)?20.toHaveBeenCalled():?來(lái)判斷mockfunction是否被調(diào)?過21.toHaveBeenCalledTimes(number):?來(lái)判斷mockfunction被調(diào)?的次數(shù)22.assertions(number):驗(yàn)證在?個(gè)測(cè)試?例中有number個(gè)斷?被調(diào)?23.extend(matchers):?定義?些斷?Enzyme三種渲染?法1.shallow:淺渲染,是對(duì)官?的ShallowRenderer的封裝。將組件渲染成虛擬DOM對(duì)象,只會(huì)渲染第?層,?組件將不會(huì)被渲染出來(lái),使得效率?常?。不需要DOM環(huán)境,并可以使?jQuery的?式訪問組件的信息2.render:靜態(tài)渲染,它將React組件渲染成靜態(tài)的HTML字符串,然后使?Cheerio這個(gè)庫(kù)解析這段字符串,并返回?個(gè)Cheerio的實(shí)例對(duì)象,可以?來(lái)分析組件的html結(jié)構(gòu)3.mount:完全渲染,它將組件渲染加載成?個(gè)真實(shí)的DOM節(jié)點(diǎn),?來(lái)測(cè)試DOMAPI的交互和組件的?命周期。?到了jsdom來(lái)模擬瀏覽器環(huán)境三種?法中,shallow和mount因?yàn)榉祷氐氖荄OM對(duì)象,可以?simulate進(jìn)?交互模擬,?render?法不可以。?般shallow?法就可以滿?需求,如果需要對(duì)?組件進(jìn)?判斷,需要使?render,如果需要測(cè)試組件的?命周期,需要使?mount?法。常??法1.simulate(event,mock):模擬事件,?來(lái)觸發(fā)事件,event為事件名稱,mock為?個(gè)eventobject2.instance():返回組件的實(shí)例3.find(selector):根據(jù)選擇器查找節(jié)點(diǎn),selector可以是CSS中的選擇器,或者是組件的構(gòu)造函數(shù),組件的displayname等4.at(index):返回?個(gè)渲染過的對(duì)象5.get(index):返回?個(gè)reactnode,要測(cè)試它,需要重新渲染6.contains(nodeOrNodes):當(dāng)前對(duì)象是否包含參數(shù)重點(diǎn)node,參數(shù)類型為react對(duì)象或?qū)ο髷?shù)組7.text():返回當(dāng)前組件的?本內(nèi)容8.html():返回當(dāng)前組件的HTML代碼形式9.props():返回根組件的所有屬性10.prop(key):返回根組件的指定屬性11.state():返回根組件的狀態(tài)12.setState(nextState):設(shè)置根組件的狀態(tài)13.setProps(nextProps):設(shè)置根組件的屬性編寫測(cè)試?例組件代碼todo-list/index.jsimportReact,{Component}from'react';import{Button}from'antd';exportdefaultclassTodoListextendsComponent{constructor(props){super(props);this.handleTest2=this.handleTest2.bind(this);}handleTest=()=>{console.log('test');}handleTest2(){console.log('test2');}componentDidMount(){}render(){return(<divclassName="todo-list">{ps.list.map((todo,index)=>(<divkey={index}><spanclassName="item-text">{todo}</span><ButtononClick={()=>ps.deleteTodo(index)}>done</Button></div>))}</div>);}}復(fù)制代碼測(cè)試?件setup設(shè)置constprops={list:['first','second'],deleteTodo:jest.fn(),};constsetup=()=>{constwrapper=shallow(<TodoList{...props}/>);return{props,wrapper,};};constsetupByRender=()=>{constwrapper=render(<TodoList{...props}/>);return{props,wrapper,};};constsetupByMount=()=>{constwrapper=mount(<TodoList{...props}/>);return{props,wrapper,};};復(fù)制代碼使?snapshot進(jìn)?UI測(cè)試it('renderscorrectly',()=>{consttree=renderer.create(<TodoList{...props}/>).toJSON();expect(tree).toMatchSnapshot();});復(fù)制代碼當(dāng)使?toMatchSnapshot的時(shí)候,會(huì)?成?份組件DOM的快照,以后每次運(yùn)?測(cè)試?例的時(shí)候,都會(huì)?成?份組件快照和第?次?成的快照進(jìn)?對(duì)?,如果對(duì)組件的結(jié)構(gòu)進(jìn)?修改,那么?成的快照就會(huì)對(duì)?失敗??梢酝ㄟ^更新快照重新進(jìn)?UI測(cè)試。對(duì)組件節(jié)點(diǎn)進(jìn)?測(cè)試it('shouldhasButton',()=>{const{wrapper}=setup();expect(wrapper.find('Button').length).toBe(2);});it('shouldrender2item',()=>{const{wrapper}=setupByRender();expect(wrapper.find('button').length).toBe(2);});it('shouldrenderitemequal',()=>{const{wrapper}=setupByMount();wrapper.find('.item-text').forEach((node,index)=>{expect(node.text()).toBe(ps().list[index])});});it('clickitemtobedone',()=>{const{wrapper}=setupByMount();wrapper.find('Button').at(0).simulate('click');expect(props.deleteTodo).toBeCalled();});復(fù)制代碼判斷組件是否有Button這個(gè)組件,因?yàn)椴恍枰秩?節(jié)點(diǎn),所以使?shallow?法進(jìn)?組件的渲染,因?yàn)閜rops的list有兩項(xiàng),所以預(yù)期應(yīng)該有兩個(gè)Button組件。判斷組件是否有button這個(gè)元素,因?yàn)閎utton是Button組件?的元素,所有使?render?法進(jìn)?渲染,預(yù)期也會(huì)找到連個(gè)button元素。判斷組件的內(nèi)容,使?mount?法進(jìn)?渲染,然后使?forEach判斷.item-text的內(nèi)容是否和傳?的值相等使?simulate來(lái)觸發(fā)click事件,因?yàn)閐eleteTodo被mock了,所以可以?deleteTodo?法時(shí)候被調(diào)?來(lái)判斷click事件是否被觸發(fā)。測(cè)試組件?命周期//使?spy替?的時(shí)候,在測(cè)試?例結(jié)束后,要對(duì)spy進(jìn)?restore,不然這個(gè)spy會(huì)?直存在,并且?法對(duì)相同的?法再次進(jìn)?spy。it('callscomponentDidMount',()=>{constcomponentDidMountSpy=jest.spyOn(TodoLtotype,'componentDidMount');const{wrapper}=setup();expect(componentDidMountSpy).toHaveBeenCalled();componentDidMountSpy.mockRestore();});復(fù)制代碼使?spyOn來(lái)mock組件的componentDidMount,替?函數(shù)要在組件渲染之前,所有替?函數(shù)要定義在setup執(zhí)?之前,并且在判斷以后要對(duì)替?函數(shù)restore,不然這個(gè)替?函數(shù)會(huì)?直存在,且被mock的那個(gè)函數(shù)?法被再次mock。測(cè)試組件的內(nèi)部函數(shù)it('callscomponenthandleTest',()=>{//class中使?箭頭函數(shù)來(lái)定義?法const{wrapper}=setup();constspyFunction=jest.spyOn(wrapper.instance(),'handleTest');wrapper.instance().handleTest();expect(spyFunction).toHaveBeenCalled();spyFunction.mockRestore();});it('callscomponenthandleTest2',()=>{//在constructor使?bind來(lái)定義?法constspyFunction=jest.spyOn(TodoLtotype,'handleTest2');const{wrapper}=setup();wrapper.instance().handleTest2();expect(spyFunction).toHaveBeenCalled();spyFunction.mockRestore();});復(fù)制代碼使?instance函數(shù)來(lái)取得組件的實(shí)例,并?spyOn?法來(lái)mock實(shí)例上的內(nèi)部?法,然后?這個(gè)實(shí)例去調(diào)?那個(gè)內(nèi)部?法,就可以?替?來(lái)判斷這個(gè)內(nèi)部函數(shù)是否被調(diào)?。如果內(nèi)部?法是?箭頭函數(shù)來(lái)定義的時(shí)候,需要對(duì)實(shí)例進(jìn)?mock;如果內(nèi)部?法是通過正常的?式或者bind的?式定義的,那么需要對(duì)組件的prototype進(jìn)?mock。其實(shí)對(duì)?命周期或者內(nèi)部函數(shù)的測(cè)試,可以通過?些state的改變進(jìn)?判斷,因?yàn)檫@些函數(shù)的調(diào)??般都會(huì)對(duì)組件的state進(jìn)??些操作。ManualMocks1.對(duì)全局的模塊(moduleName)進(jìn)??動(dòng)模擬,需要在node_modules平級(jí)的位置新建?個(gè)__mocks__?件夾,并在?件夾中新建?個(gè)moduleName的?件2.對(duì)某個(gè)?件(fileName)進(jìn)??動(dòng)模擬,需要在被模擬的?件平級(jí)的位置新建?個(gè)__mocks__?件夾,然后在?件夾中新建?個(gè)fileName的?件add/index.jsimport{add}from'lodash';import{multip}from'../../utils/index';exportdefaultfunctionsum(a,b){returnadd(a,b);}exportfunctionm(a,b){returnmultip(a,b);}復(fù)制代碼add/__test__/index.test.jsimportsum,{m}from'../index';jest.mock('lodash');jest.mock('../../../utils/index');describe('testmocks',()=>{it('testsum',()=>{expect(sum(2,3)).toEqual(5);});it('testmutilp',()=>{expect(m(2,3)).toEqual(7);});});復(fù)制代碼_mocks_:在測(cè)試?件中使?mock()?法對(duì)要進(jìn)?mock的?件進(jìn)?引?,Jest就會(huì)?動(dòng)去尋找對(duì)應(yīng)的__mocks__中的?件并進(jìn)?替換,lodash中的add和utils中的multip?法就會(huì)被mock成對(duì)應(yīng)的?法??梢允??動(dòng)代理的?式對(duì)項(xiàng)?的異步組件庫(kù)(fetch、axios)進(jìn)?mock,或者使?fetch-mock、jest-fetch-mock來(lái)模擬異步請(qǐng)求。對(duì)異步?法進(jìn)?測(cè)試async/index.jsimportrequestfrom'./request';exportfunctiongetUserName(userID){returnrequest(`/users/${userID}`).then(user=>);}async/request.jsconsthttp=require('http');exportdefaultfunctionrequest(url){returnnewPromise((resolve)=>{//Thisisanexampleofanhttprequest,forexampletofetch//userdatafromanAPI.//Thismoduleisbeingmockedin__mocks__/request.jshttp.get({path:url},(response)=>{letdata='';response.on('data',_data=>(data+=_data));response.on('end',()=>resolve(data));});});}復(fù)制代碼mockrequest:constusers={4:{name:'hehe',},5:{name:'haha',},};exportdefaultfunctionrequest(url){returnnewPromise((resolve,reject)=>{constuserID=parseInt(url.substr('/users/'.length),10);process.nextTick(()=>{users[userID]?resolve(users[userID]):reject({error:`Userwith${userID}notfound.`,});});});}復(fù)制代碼request.js可以看成是?個(gè)?于請(qǐng)求數(shù)據(jù)的模塊,?動(dòng)mock這個(gè)模塊,使它返回?個(gè)Promise對(duì)象,?于對(duì)異步的處理。測(cè)試Promise//使?'.resolves'來(lái)測(cè)試promise成功時(shí)返回的值it('workswithresolves',()=>{//expect.assertions(1);expect(user.getUserName(5)).resolves.toEqual('haha')});//使?'.rejects'來(lái)測(cè)試promise失敗時(shí)返回的值it('workswithrejects',()=>{expect.assertions(1);returnexpect(user.getUserName(3)).rejects.toEqual({error:'Userwith3notfound.',});});//使?promise的返回值來(lái)進(jìn)?測(cè)試it('testresolvewithpromise',()=>{expect.assertions(1);returnuser.getUserName(4).then((data)=>{expect(data).toEqual('hehe');});});it('testerrorwithpromise',()=>{expect.assertions(1);returnuser.getUserName(2).catch((e)=>{expect(e).toEqual({error:'Userwith2notfound.',});});});復(fù)制代碼當(dāng)對(duì)Promise進(jìn)?測(cè)試時(shí),?定要在斷?之前加?個(gè)return,不然沒有等到Promise的返回,測(cè)試函數(shù)就會(huì)結(jié)束??梢允?.promises/.rejects對(duì)返回的值進(jìn)?獲取,或者使?then/catch?法進(jìn)?判斷。測(cè)試Async/Await//使?async/await來(lái)測(cè)試resolveit('worksresolvewithasync/await',async()=>{expect.assertions(1);constdata=awaituser.getUserName(4);expect(data).toEqual('hehe');});//使?async/await來(lái)測(cè)試rejectit('worksrejectwithasync/await',async()=>{expect.assertions(1);try{awaituser.getUserName(1);}catch(e){expect(e).toEqual({error:'Userwith1notfound.',});}});復(fù)制代碼使?async不?進(jìn)?return返回,并且要使?try/catch來(lái)對(duì)異常進(jìn)?捕獲。代碼覆蓋率代碼覆蓋率是?個(gè)測(cè)試指標(biāo),?來(lái)描述測(cè)試?例的代碼是否都被執(zhí)?。統(tǒng)計(jì)代碼覆蓋率?般要借助代碼覆蓋?具,Jest集成了Istanbul這個(gè)代碼覆蓋?具。四個(gè)測(cè)量維度1.?覆蓋率(linecoverage):是否測(cè)試?例的每??都執(zhí)?了2.函數(shù)覆蓋率(functioncoverage):師傅測(cè)試?例的每?個(gè)函數(shù)都調(diào)?了3.分?覆蓋率(branchcoverage):是否測(cè)試?例的每個(gè)if代碼塊都執(zhí)?了4.語(yǔ)句覆蓋率(statementcoverage):是否測(cè)試?例的每個(gè)語(yǔ)句都執(zhí)?了在四個(gè)維度中,如果代碼書寫的很規(guī)范,?覆蓋率和語(yǔ)句覆蓋率應(yīng)該是?樣的。會(huì)觸發(fā)分?覆蓋率的情況有很多種,主要有以下?種:||,&&,?,!if語(yǔ)句switch語(yǔ)句例?functiontest(a,b){a=a||0;b=b||0;if(a&&b){returna+b;}else{return0;}}test(1
溫馨提示
- 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 關(guān)于安全主題班會(huì)主持人演講稿模板5篇
- 美術(shù)教師讀書心得(12篇)
- 教育培訓(xùn)班項(xiàng)目可行性研究報(bào)告
- 教案拼音a教案8篇
- 環(huán)保工程招投標(biāo)代理合同模板
- 學(xué)校運(yùn)動(dòng)場(chǎng)地坪漆施工協(xié)議
- 生態(tài)觀光魚塘租賃合同
- 仲裁協(xié)議書范本示例
- 舞蹈比賽贊助商代表合同
- 舊樓改造備案委托協(xié)議
- 五年級(jí)上冊(cè)解方程練習(xí)100題及答案
- 設(shè)計(jì)變更控制程序
- 三年級(jí)硬筆書法課件
- 2024全球量子產(chǎn)業(yè)發(fā)展報(bào)告
- 場(chǎng)地移交安全管理協(xié)議書
- 醫(yī)院卒中中心建設(shè)各種制度、流程匯編
- 重慶市江北區(qū)2023-2024學(xué)年六年級(jí)下學(xué)期期末考試數(shù)學(xué)試題
- 軍隊(duì)文職聘用合同管理規(guī)定
- 2024年貴州省安順市西秀區(qū)小升初語(yǔ)文試卷
- 2024-2029年中國(guó)兒童牙冠行業(yè)市場(chǎng)現(xiàn)狀分析及競(jìng)爭(zhēng)格局與投資發(fā)展研究報(bào)告
- 新時(shí)代鐵路發(fā)展面對(duì)面全文內(nèi)容
評(píng)論
0/150
提交評(píng)論