如何提高產品開發(fā)品質_第1頁
如何提高產品開發(fā)品質_第2頁
如何提高產品開發(fā)品質_第3頁
如何提高產品開發(fā)品質_第4頁
如何提高產品開發(fā)品質_第5頁
已閱讀5頁,還剩56頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、如何提高產品開發(fā)品質如何提高產品開發(fā)品質講解內容講解內容目前開發(fā)過程存在的問題1產品開發(fā)品質保障流程2代碼重構3測試驅動4日構建5一、目前開發(fā)過程存在的問題一、目前開發(fā)過程存在的問題l沒有完善的品質保障流程沒有完善的品質保障流程l質量低下的代碼質量低下的代碼l不重視測試不重視測試產品開發(fā)流程現(xiàn)狀產品開發(fā)流程現(xiàn)狀開發(fā)人員編寫代碼開發(fā)人員編寫代碼調試調試, 肉眼觀察肉眼觀察有問題有問題沒問題(自認為)沒問題(自認為)可交付的代碼可交付的代碼編譯編譯修正編譯錯誤修正編譯錯誤登記到登記到JIRAJIRA上上客戶提出需求或客戶提出需求或現(xiàn)場發(fā)現(xiàn)現(xiàn)場發(fā)現(xiàn)bugbug產品品質管理嚴重缺失產品品質管理嚴重缺失

2、 該流程的最終目標和工作重心都是完成產品功能開發(fā),品質管理嚴重缺失。產品的開發(fā)質量完全靠開發(fā)人員的個人責任心以及工作經驗來保障,缺乏一個穩(wěn)定可靠的質量保障流程。這種流程開發(fā)出來的產品往往是質量不可靠,需要經常返工的劣質產品。質量低下的代碼是導致產品品質質量低下的代碼是導致產品品質不好的根本原因不好的根本原因質量低下的代碼體現(xiàn)在以下幾個方面:l重復的代碼l過長的函數(shù)l過大類l過長的參數(shù)列表l過度復雜的邏輯判斷l(xiāng)數(shù)據(jù)泥團沒有專職測試人員來進行功能性沒有專職測試人員來進行功能性測試工作測試工作在目前的開發(fā)流程中,開發(fā)出來的代碼只經過開發(fā)人員自己簡單的測試,沒有專職的測試人員來進行詳細的功能性測試。這

3、樣導致的結果往往是提交到現(xiàn)場的代碼會帶有不少BUG,一定要經過多次返工才能達到較高的品質。而且這樣做的另一個后果是把客戶當作測試人員,會給客戶留下產品品質不穩(wěn)定這樣一種非常不好的客戶體驗。開發(fā)人員在開發(fā)過程中不重視單開發(fā)人員在開發(fā)過程中不重視單元測試元測試單元測試是提高產品品質非常重要的一個方法,而我們的開發(fā)人員往往會忽視這一點。如果沒有單元測試,僅僅依靠測試人員的功能性測試,那么這樣的測試工作量會非常大,每次修改一個功能,可能會影響到的其他功能都要一一測試,不僅測試時間會非常長,而且效果也不好,很多細節(jié)不一定每次都能測到,這些都是產生BUG的隱患。同時由于我們業(yè)務需求都非常復雜多變的,沒有一

4、個完善自動化測試流程,而僅僅依靠人工測試,對產品品質的影響是不言而喻的。我們的目標!我們的目標!l編寫出邏輯清晰、結構簡潔、擴展性良好、可測試性高的優(yōu)秀代碼。l強化單元測試工作,提高單元測試覆蓋率,搭建自動單元測試集,通過日構建來持續(xù)集成,對產品質量進行全面控制。l通過嚴格的產品質量管理流程,強化質量管理工作,將所有BUG消滅在公司內部。二、產品開發(fā)品質保障流程二、產品開發(fā)品質保障流程開發(fā)質量管理開發(fā)質量管理本開發(fā)流程的目標是開發(fā)出質量優(yōu)良的產品,流程的重心在于質量管控,通過質量保障人員對產品質量進行全面把關。l對于沒有編寫單元測試的代碼直接打回!l質量保障人員負責進行功能性測試,并對提交出去

5、的代碼負責。l質量保障人員另一個職責是思考如何持續(xù)改進產品質量。需求管控需求管控l對每個需求進行分級評審,最大程度的降低需求變更的頻度。l所有需求開發(fā)前都經過內部評審,對于一些復雜需求把握更加準確,不至于在開發(fā)時候產生較大偏差。l所有需求的開發(fā)工作都有經過客戶簽字的開發(fā)工作量評估,為商務工作開展創(chuàng)造有利條件。l所有需求都有詳細開發(fā)計劃,片區(qū)人員可以安排相應的測試計劃。全過程管控全過程管控l所有缺陷和經過評審的需求都必須在JIRA上登記,否則不予開發(fā)。l開發(fā)計劃通過JIRA進行精確體現(xiàn)。l片區(qū)人員可以通過JIRA實時跟蹤產品開發(fā)進度。l方便后續(xù)各類工作量的統(tǒng)計。三、利用代碼重構來提高代碼質量三、

6、利用代碼重構來提高代碼質量 重構(Refactoring):是對軟件內部結構的一種調整,目的是在不改變外部行為的前提下,提高其可理解性,降低其修改成本為什么重構(為什么重構(1)l改進軟件的設計。l程序員對代碼所做的為了滿足短期利益代碼改動,或再沒有完全清楚增個架構下的改動,都很容易是代碼失去它的清晰結構,偏離需求或設計。而這些改動的積累很容易使代碼偏離它原先設計的初衷而變得不可立即和無法維護。l重構則幫助重新組織代碼,重新清晰的體現(xiàn)結構和進一步改進設計。為什么重構(為什么重構(2)l提高代碼質量,更易被理解l容易理解的代碼可以很容易的維護和做進一步的開發(fā)。即使對寫這些代碼的程序員本身,容易理

7、解代碼也可以幫助容易地做修改。程序代碼也是文檔。而代碼首先是寫給人看的,讓后才是給計算機看的。l重構幫助盡早的發(fā)現(xiàn)錯(Bugs)l重構是一個code review和反饋的過程。在另一個時段重新審視自己或別人代碼,可以更容易的發(fā)現(xiàn)問題和加深對代碼的理解。l重構是一個良好的軟件開發(fā)習慣。為什么重構(為什么重構(3)l重構可以提高開發(fā)速度l重構對設計和代碼的改進,都可以有效的提高開發(fā)速度。好的設計和代碼質量實體提高開發(fā)速度的關鍵。在一個有缺陷的設計和混亂代碼基礎上的開發(fā),即使表面上進度較快,但本質是試延后對設計缺陷的發(fā)現(xiàn)和對錯誤的修改,也就是延后了開發(fā)風險,最終要在開發(fā)的后期付出更多的時間和代價。l

8、項目的維護成本遠高于開發(fā)成本.何時重構何時重構? ?l添加或者修改功能時一并重構l為了增加一個新的功能或者修改原有的功能,程序員需要首先讀懂現(xiàn)有的代碼。l修補錯誤時一并重構l為了修復一個Bug,程序員需要讀懂現(xiàn)有的代碼。lCode Review時一并重構何時不該重構何時不該重構? ?l代碼太混亂,設計完全錯誤。與其Refactor,不如重寫。l明天是DeadLinel永遠不要做Last-Minute-Change。推遲重構,但不可以忽略,即使進入產品期的代碼都正確的運行。重構方法介紹:提取函數(shù)(重構方法介紹:提取函數(shù)(1)String name = request.getParameter(N

9、ame);if( name != null & name.length() 0 ).String age = request.getParameter(Age);if( age != null & age.length() 0 ).String name = request.getParameter(Name);if( !isNullOrEmpty( name ) ).String age = request.getParameter(Age);if( !isNullOrEmpty( age ) ).private boolean isNullOrEmpty( final St

10、ring string )if( string != null & string.length() 0 )return true;elsereturn false;重構方法介紹:提取函數(shù)(重構方法介紹:提取函數(shù)(2) 提取函數(shù)是我最常用的重構手法之一。當我看見一個過長的函數(shù)或者一段需要注釋才能讓人理解用途的代碼,我就會將這段代碼放進一個獨立的函數(shù)中。有數(shù)個原因造成我喜歡簡短而有良好命名的函數(shù)。首先,如果每個函數(shù)的粒度都很小,那么函數(shù)之間彼此復用的機會就更大;其次,這會使高層函數(shù)讀起來就像一系列注釋;再者,如果函數(shù)都是細粒度,那么函數(shù)的覆寫(override )也會更容易些: 的確,如果

11、你習慣了看大型函數(shù),恐怕需要一段時問才能適應達種新風格,而且只有當你能給小型函數(shù)很好地命名時,它們才能真正起作用,所以你需要在函數(shù)名稱下點功夫,一個函數(shù)多長才算合適?在我看來.長度不是問題,關鍵在于函數(shù)名稱和函數(shù)本體之間的語義距離,如果提煉動作可以強化代碼的清晰度,那就去做,就是函數(shù)名稱比提煉出來的代碼還長也無所謂。重構方法介紹:去除臨時變量重構方法介紹:去除臨時變量(1)(1)重構方法介紹:去除臨時變量重構方法介紹:去除臨時變量(2)(2)我喜歡盡量除去函數(shù)內的臨時變量。臨時變量往往形成問題,它們會導致大量參數(shù)被傳來傳去,而其實完全沒有這種必要。你很容易失去它們的蹤跡,尤其在長長的函數(shù)之中更

12、是如此。而且,臨時變量的存在,往往會阻礙提取函數(shù)等其他重構手法的進行。重構方法介紹:重新命名函數(shù)重構方法介紹:重新命名函數(shù)(1)(1)public String getItemName (int itemSort,String itemName)return +itemSort+、+itemName; public String formatItemName (int itemSort,String itemName)return +itemSort+、+itemName; 重構方法介紹:重新命名函數(shù)重構方法介紹:重新命名函數(shù)(2)(2)我極力提倡的一種編程風格就是:將復雜的處理過程分解成小函

13、數(shù)。但是,如果做得不好,這會使你費盡周折卻弄不清楚這些小函數(shù)各白的用途、.要避免這種麻煩,關鍵就在于給函數(shù)起一個好名稱;函數(shù)的名稱應該準確表達它的用途;給函數(shù)命名有一個好辦法。首先考慮應該給這個函數(shù)寫上一句怎樣的注釋,然后想辦法將注釋變成函數(shù)名稱。人生不如意十之八九:你常常無法第一次就給函數(shù)起一個好名稱,這時候你可能會想,就這樣將就著吧,畢竟只是一個名稱而已。當心!這是惡魔的召喚,是通向混亂之路,千萬不要被它誘惑!如果你看到一個函數(shù)名稱不能很好地表達它的用途,應該馬上加以修改。記住,你的代碼首先是為人寫的,其次才是為計算器寫的。而人需要良好名稱的函數(shù)。想想過去曾經浪費的無數(shù)時間吧,如果給每個函

14、數(shù)都起一個良好的名稱,也許你可以節(jié)約好多時間。取一個好名稱并不容易,需要經驗,要想成為一個真正的編程高手,取名稱的水平是至關重要的。重構方法介紹:以多態(tài)取代條件重構方法介紹:以多態(tài)取代條件表達式(表達式(1 1)public class PlanUtil public void setPlanState(int planYear,int itemId,int dataType)switch dataType case 1:setPrePlanState(planYear,itemId); case 2:setColPlanState(planYear,itemId); case 3:setAf

15、tPlanState(planYear,itemId); default:throw new RuntimeException(不正確的計劃類型:+dataType);/.更新建議計劃狀態(tài)public void setPrePlanState /.更新綜合計劃狀態(tài)public void setColPlanState. /.更新開工計劃狀態(tài)public void setAftPlanState.public class PlanUtil public static PlanUtil create (int dataType)switch (dataType)case 1:return new

16、PrePlanUtil();case 2:return new ColPlanUtil();case 3:return new AftPlanUtil();default:throw new RuntimeException(不正確的計劃類型:+dataType);public abstract void setPlanState (int planYear,int itemId,int dataType);public abstract void savePlan (int planYear,int itemId,int dataType);重構方法介紹:以多態(tài)取代條件重構方法介紹:以多態(tài)取

17、代條件表達式(表達式(2)/保存計劃數(shù)據(jù)public void savePlan(int planYear,int itemId,int dataType)switch dataTypecase 1:savePrePlan(planYear,itemId);case 2:saveColPlan(planYear,itemId);case 3:saveAftPlan(planYear,itemId); default: throw new RuntimeException(不正確的計劃類型:+dataType);/.保存建議計劃數(shù)據(jù)public void savePrePlan /.保存綜合計劃

18、數(shù)據(jù)public void saveColPlan/.保存開工計劃數(shù)據(jù)public void saveAftPlanpublic class PrePlanUtil extends PlanUtil public void setPlanState (int planYear,int itemId,int dataType). 更新建議計劃狀態(tài)方法public void savePlan (int planYear,int itemId,int dataType)保存建議計劃數(shù)據(jù)方法public class ColPlanUtil extends PlanUtil public void se

19、tPlanState (int planYear,int itemId,int dataType). 更新綜合計劃狀態(tài)方法public void savePlan (int planYear,int itemId,int dataType)保存綜合計劃數(shù)據(jù)方法重構方法介紹:以多態(tài)取代條件重構方法介紹:以多態(tài)取代條件表達式(表達式(3)/調用更新計劃狀態(tài)的方法planUtil.setPlanState(year,itemId,dataType);/調用保存計劃數(shù)據(jù)的方法planUtil.savePlanyear,itemId,dataType);public class AftPlanUtil

20、extends PlanUtil public void setPlanState (int planYear,int itemId,int dataType). 更新開工計劃狀態(tài)方法public void savePlan (int planYear,int itemId,int dataType)保存開工計劃數(shù)據(jù)方法/調用PlanUtil planUtil = PlanUtil .create(dataType);/調用更新計劃狀態(tài)的方法planUtil.setPlanState(year,itemId,dataType);/調用保存計劃數(shù)據(jù)的方法planUtil.savePlan (ye

21、ar,itemId,dataType);重構方法介紹:以多態(tài)取代條件重構方法介紹:以多態(tài)取代條件表達式(表達式(4)l多態(tài)最根本的好處就是:如果你需要根據(jù)對象的不同型別而采取不同的行為,多態(tài)使你不必編寫明顯的條件式。正因為有了多態(tài),所以你會發(fā)現(xiàn):針對type code(型別碼)而寫的switch語句,以及針對type string(型別名稱字符串)而寫的if-then-else語句在面向對象程序中很少出現(xiàn)。l多態(tài)能夠給你帶來很多好處。如果同一組條件式在程序許多地點出現(xiàn),那么使用多態(tài)的收益是最大的。使用條件式時,如果你想添加一種新型別,就必須杳找并更新所有條件式。但如果改用多態(tài),只需建一個新的s

22、ubclass并在其中提供適當?shù)暮瘮?shù)就行了。class用戶不需要了解這個subclass,這就大大降低了系統(tǒng)各部分之間的耦合程度,使系統(tǒng)升級.更加容易。重構方法介紹:以委托取代繼承重構方法介紹:以委托取代繼承(1)(1)/繼承解決方案public classBusPlanManagerServiceImpl public void setPlanState (int planYear,int itemId,int dataType). 更新建議計劃狀態(tài)方法 public void savePlan (int planYear,int itemId,int dataType)保存建議計劃數(shù)據(jù)方法

23、public class PrePlanService extends BusPlanManagerServiceImpl .public class ColPlanService extends BusPlanManagerServiceImpl .public class AftPlanService extends BusPlanManagerServiceImpl ./委托解決方案public classBusPlanManagerServiceImplpublic void setPlanState (int planYear,int itemId,int dataType)Plan

24、Util planUtil = PlanUtil .create(dataType);/調用更新計劃狀態(tài)的方法planUtil.setPlanState(year,itemId,dataType);public void savePlan (int planYear,int itemId,int dataType)PlanUtil planUtil = PlanUtil .create(dataType);/調用更新計劃狀態(tài)的方法planUtil. savePlan (year,itemId,dataType); 重構方法介紹:以委托取代繼承重構方法介紹:以委托取代繼承(2)(2)l繼承是一件

25、很棒的事,但有時候它并不是你要的。常常你會遇到這樣的情況:一開始你繼承了一個class ,隨后發(fā)現(xiàn)superclass中的許多操作井不真正適用于subclass。這種情況下你所擁有的接口并末真正反映出class的功能。或者,你可能發(fā)現(xiàn)你從superclass中繼承了一大堆subclas并不需要的數(shù)據(jù),抑或者你可能發(fā)現(xiàn)superclass中的某些protected函數(shù)對subclass并沒有什么意義。l你可以選擇容忍,并接受傳統(tǒng)說法:subclass可以只使用superclas、功能的一部分。但這樣做的結果是:代碼傳達的信息與你的意圖南轅北轍,這是一種混淆,你應該將它去除。如果以委托取代繼承,你

26、可以更清楚地表明:你只需要受托類的一部分功能。接口中的哪一部分應該被使用,哪一部分應該被忽略,完全由你主導控制。這樣做的成本則是需耍額外寫出委托函數(shù),但這些函數(shù)都非常簡單,極少可能出錯。重構方法介紹:引入參數(shù)對象重構方法介紹:引入參數(shù)對象(1)public List getYearPlanList (String operatorID, String planYear,String iSeason, String planType,String dataType).public List getLastYearPlanList (String operatorID, String planYe

27、ar,String iSeason, String planType,String dataType)public void fillPlanData (String operatorID, String planYear,String iSeason, String planType,String dataType)PlanData planData=new PlanData();planData.setYeraPlanList(getYearPlanList (operatorID,planYear, iSeason,planType,dataType);planData.setLastY

28、eraPlanList(getLastYearPlanList (operatorID,planYear, iSeason,planType,dataType);public class PlanParamObj private String operatorID;private String planYear;private String iSeason;private String planType,;private String dataType;public PlanParamObj (String operatorID, String planYear,String iSeason,

29、 String planType,String dataType) this.operatorID=operatorID;this.planYear=planYear;this.iSeason=iSeason;this.planType=planType;this.dataType=dataType;重構方法介紹:引入參數(shù)對象重構方法介紹:引入參數(shù)對象(2)public List getYearPlanList (PlanParamObj paramObj).public List getLastYearPlanList (PlanParamObj paramObj).public void

30、fillPlanData (String operatorID, String planYear,String iSeason, String planType,String dataType)PlanParamObj paramObj = new PlanParamObj (operatorID,planYear, iSeason,planType,dataType);PlanData planData=new PlanData();planData.setYeraPlanList(getYearPlanList (paramObj);planData.setLastYeraPlanList

31、(getLastYearPlanList (paramObj );重構方法介紹:引入參數(shù)對象重構方法介紹:引入參數(shù)對象(3)l你常會看到特定的數(shù)組參數(shù)總是一起被傳遞??赡苡泻脦讉€函數(shù)都使用這一組參數(shù),這些函數(shù)可能隸屬同個class,也可能隸屬不同的classes。這樣一組參數(shù)就是所謂的data Clump(數(shù)據(jù)泥團),我們可以運用一個對象包裝所有這些數(shù)據(jù),再以該對象取代它們。哪伯只是為了把這些數(shù)據(jù)組織在一起,這樣做也是值得的。本項重構的價值在于縮短了參數(shù)列的長度,而你知道,過長的參數(shù)列總是難以理解的。此外,新對象所定義的訪問函數(shù)還可以使代碼更具一致性,這又進一步降低了代碼的理解難度和修改難度。

32、l本項重構還可以帶給你更多好處。當你把這些參數(shù)組織到起之后,往往很快可以發(fā)現(xiàn)一些可被移至新建class的行為。通常,原本使用那些參數(shù)的函數(shù)對那些參數(shù)會有一些共通措施,如果將這些共通行為移到新對象中,你可以減少很多重復代碼重構方法介紹:函數(shù)遷移重構方法介紹:函數(shù)遷移(1)(1)public class RepUtilFunc private List initFundList().this.copyFundView(fView,planView); /匯總投資計劃數(shù)據(jù)private void copyFundView (FundView fView,PlanView planView)fView

33、.setFund(fView.getFund()+planView.getFund();fView.setUpprefund(fView.getUpprefund()+planView.getUpprefund();fView.setDownprefund(fView.getDownprefund()+planView.getDownprefund();public class RepUtilFunc private List initFundList().fView.copyFundView(planView); /匯總投資計劃數(shù)據(jù)重構方法介紹:重構方法介紹:函數(shù)遷移函數(shù)遷移(2)(2)pu

34、blic class FundView private double fund;private String upprefund; private String downprefund;getset方法public class FundView private double fund;private String upprefund; private String downprefund;getset方法public void copyFundView (PlanView planView)this.setFund(this.getFund()+planView.getFund();this.

35、setUpprefund(this.getUpprefund()+planView.getUpprefund();this.setDownprefund(this.getDownprefund()+planView.getDownprefund();重構方法介紹:重構方法介紹:函數(shù)遷移函數(shù)遷移(3)(3)函數(shù)遷移是重構理論的支柱。如果一個class有太多行為,或如果一個class與另一個class有太多合作而形成高度耦合,我就會遷移函數(shù)。通過這種手段,我可以使系統(tǒng)中的classes更簡單,這些classes最終也將更干凈利落地實現(xiàn)系統(tǒng)交付的任務。常常我會瀏覽class的所有函數(shù),從中尋找這樣的

36、函數(shù),使用另一個對象的次數(shù)比使用自己所駐對象的次數(shù)還多,就會進行函數(shù)遷移。重構方法介紹:將過程化設計轉重構方法介紹:將過程化設計轉換為面向對象設計換為面向對象設計l有時間的話用一個實際例子進行展示。四、測試驅動開發(fā)方法簡介四、測試驅動開發(fā)方法簡介測試驅動開發(fā)(Test Driven Development,英文縮寫TDD)是極限編程的一個重要組成部分,它的基本思想就是在開發(fā)功能代碼之前,先編寫代碼的單元測試用例。也就是說在明確要開發(fā)某個功能后,首先思考如何對這個功能進行測試,并完成測試用例的編寫,然后編寫相關的代碼滿足這些測試用例。循環(huán)進行添加其他功能,直到完成全部功能的開發(fā)。代碼整潔可用(c

37、lean code that works) 是測試驅動開發(fā)所追求的目標。測試驅動開發(fā)優(yōu)點測試驅動開發(fā)優(yōu)點(1)(1)l需求向來就是軟件開發(fā)過程中感覺最不好明確描述、易變的東西。這里說的需求不只是指用戶的需求,還包括對代碼的使用需求。很多開發(fā)人員最害怕的就是后期還要修改某個類或者函數(shù)的接口進行修改或者擴展,為什么會發(fā)生這樣的事情就是因為這部分代碼的使用需求沒有很好的描述。測試驅動開發(fā)就是通過編寫測試用例,先考慮代碼的使用需求(包括功能、過程、接口等),而且這個描述是無二義的,可執(zhí)行驗證的。 l通過編寫這部分代碼的測試用例,對其功能的分解、使用過程、接口都進行了設計。而且這種從使用角度對代碼的設計

38、通常更符合后期開發(fā)的需求??蓽y試的要求,對代碼的內聚性的提高和復用都非常有益。因此測試驅動開發(fā)也是一種代碼設計的過程。 l開發(fā)人員通常對編寫文檔非常厭煩,但要使用、理解別人的代碼時通常又希望能有文檔進行指導。而測試驅動開發(fā)過程中產生的測試用例代碼就是對代碼的最好的解釋。 測試驅動開發(fā)優(yōu)點測試驅動開發(fā)優(yōu)點(2)(2)l快樂工作的基礎就是對自己有信心,對自己的工作成果有信心。當前很多開發(fā)人員卻經常在擔心:“代碼是否正確?”“辛苦編寫的代碼還有沒有嚴重bug?”“修改的新代碼對其他部分有沒有影響?”。這種擔心甚至導致某些代碼應該修改卻不敢修改的地步。測試驅動開發(fā)提供的測試集就可以作為你信心的來源。

39、l當然測試驅動開發(fā)最重要的功能還在于保障代碼的正確性,能夠迅速發(fā)現(xiàn)、定位bug。而迅速發(fā)現(xiàn)、定位bug是很多開發(fā)人員的夢想。針對關鍵代碼的測試集,以及不斷完善的測試用例,為迅速發(fā)現(xiàn)、定位bug提供了條件。 l我的一段功能非常復雜的代碼使用TDD開發(fā)完成,真實環(huán)境應用中只發(fā)現(xiàn)幾個bug,而且很快被定位解決。您在應用后,也一定會為那種自信的開發(fā)過程,功能不斷增加、完善的感覺,迅速發(fā)現(xiàn)、定位bug的能力所感染,喜歡這個技術的。 測試驅動開發(fā)基本過程測試驅動開發(fā)基本過程l明確當前要完成的功能??梢杂涗洺梢粋€ TODO 列表。l快速完成針對此功能的測試用例編寫。l測試代碼編譯不通過。l編寫對應的功能代碼

40、。l測試通過。l對代碼進行重構,并保證測試通過。l循環(huán)完成所有功能的開發(fā) 測試驅動開發(fā)案例測試驅動開發(fā)案例(1)(1) 需求:實現(xiàn)Fibonacci數(shù)列Fibonacci數(shù)列簡介:Fibonacci數(shù)列從第0項開始依次為0,1,1,2,3,5,8的數(shù)列,它存在如下特點:第0,1個數(shù)為0,1。從第2個數(shù)開始,該數(shù)是前面兩個數(shù)之和。 測試驅動開發(fā)案例測試驅動開發(fā)案例(2)(2) 先編寫測試代碼 : import junit.framework.TestCase; public class FibonacciTest extends TestCasepublic void testFibonacci

41、() FibUtil fb = new FibUtil(); 編寫完測試代碼之后在Eclipse中運行該測試類,發(fā)現(xiàn)Junit運行出錯(顯示了一條紅色杠) 這是在預料之中,因為我們還沒有編寫FibUtil類。測試驅動開發(fā)案例測試驅動開發(fā)案例(3)(3) 為了使測試通過,那么下面開始編寫FibUtil類public class FibUtil 然后再次運行測試類。這時會發(fā)現(xiàn)測試成功。 測試驅動開發(fā)案例測試驅動開發(fā)案例(4)(4) 下面增加測試用例,開始測試Fibonacci數(shù)列的實現(xiàn)函數(shù)fib:public void testFibonacci() FibUtil fb = new FibUtil(); assertEquals(0,fb.fib(0); 由于出現(xiàn)編譯錯誤,所以需要在FibUtil類中增加fib方法如下:public int fib ( int i) return 0 ; 運行測試用例,通過! 測試驅動開發(fā)案例測試驅動開發(fā)案例(5)(5) 繼續(xù)增加測試用例,判斷1的情況:public void testFibonacci() FibUtil fb = new FibUtil(); assertEquals(0

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論