青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Thronds

一問你會(huì)什么 二問你做出過什么 三問你為了什么

  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  36 隨筆 :: 0 文章 :: 56 評(píng)論 :: 0 Trackbacks
一、“千般路”與“磨豆腐”   很久以前聽一個(gè)故事:從前有個(gè)小伙子,少時(shí)有大志,長大后卻無好營生,開了個(gè)豆腐作坊,每天磨豆腐累得腰酸背疼。每到夜深人靜,小伙子輾轉(zhuǎn)反側(cè),總想找條更好的“事業(yè)之路”,可是想過千百條、嘗試過幾十條路,都走不通。夜不成寢,白天干活更累,小伙子不由慨嘆:“晚上想過千般路,白天還得磨豆腐”。   不久以前看過一篇文章:《CMM欺騙了中國的軟件業(yè)》,內(nèi)容是對CMM熱的反思。CMM當(dāng)然不會(huì)主動(dòng)欺騙人,實(shí)際上是我們的軟件業(yè)自己欺騙自己。我們從來不缺少“某某模式”,“面向某某”,“某某認(rèn)證”等等聽起來美妙無比的東西,問題是實(shí)際的研發(fā)過程中能做得到碼?現(xiàn)實(shí)是殘酷的,美妙的概念漫天飛舞,開發(fā)過程仍然是作坊式的,正是:“晚上想過千般路,白天還得磨豆腐”。   中國的故事通常都有圓滿的結(jié)局,現(xiàn)在接著說“磨豆腐”的故事。過了很長時(shí)間,小伙子終于面對現(xiàn)實(shí),不再沉迷于不切實(shí)際的空想,用心磨好豆腐,閑時(shí)琢磨些個(gè)竅門,慢慢地,他的豆腐質(zhì)量越來越好,每天產(chǎn)量也越來越多,作坊越開越大,成了遠(yuǎn)近聞名的“豆腐老板”,后來,他做起了別的生意,發(fā)現(xiàn)年輕時(shí)的空想,其實(shí)很多都是可行的,因?yàn)楝F(xiàn)在“能力”和“財(cái)力”都不同了。   再說軟件開發(fā)。我們不反對任何理論、技術(shù)、方法、模式等等,但第一,您的企業(yè)或團(tuán)隊(duì)做得到嗎?不要做“如果開發(fā)時(shí)間延長一倍,就可以做到”之類毫無意義的假設(shè)。第二,做了真的有效益嗎?效益是指扣除成本之后的收益。如果不具備這兩點(diǎn),那么還是不要整天想著“千般路”,首先想想如何好好的“磨豆腐”吧。   對于所有軟件開發(fā)來說,代碼編寫都是無可逃避的“磨豆腐”。改進(jìn)代碼編寫工作,高率效低成本地開發(fā)出高質(zhì)量的代碼,對于軟件產(chǎn)品能否在激烈的競爭中勝出,對于軟件企業(yè)的生存和發(fā)展,都具有重要的現(xiàn)實(shí)意義。   本文是Visual Unit應(yīng)用的范例項(xiàng)目C++代碼文檔生成器的主題文檔,敘述的正是改進(jìn)代碼編寫工作的方法和工具,所有內(nèi)容均經(jīng)過實(shí)戰(zhàn)檢驗(yàn),具有"可行"和"效益"兩個(gè)特征,"可行"是指較低門檻或沒有門檻,憑現(xiàn)有條件即可實(shí)施;"效益"是指能產(chǎn)生立竿見影的效果。   本文所援引的范例項(xiàng)目,模擬最糟糕的開發(fā)團(tuán)隊(duì),最混亂的開發(fā)流程:由很少寫代碼的測試和預(yù)研部門開發(fā),人員不固定,時(shí)間也不固定,誰有空就寫上一些;沒有設(shè)計(jì),沒有文檔,基至也不在代碼文件中保存編碼人員的信息,成員完全依賴于閱讀代碼和測試用例來理解其他成員寫的代碼;除了簡單的命名規(guī)則外,沒有其他規(guī)范,甚至連一個(gè)函數(shù)原則上不能超過50行之類的基本規(guī)范也沒有(范例中有超過200行的函數(shù)CMacro::Unwind(),一萬多條路徑)。任何開發(fā)團(tuán)隊(duì)和開發(fā)流程都會(huì)好于范例項(xiàng)目的開發(fā)團(tuán)隊(duì)和開發(fā)流程,因此,范例所展示的方法和工具,具有"廣泛可行性"。   本文介紹如何進(jìn)行高效編碼調(diào)試和實(shí)現(xiàn)徹底的單元測試。編碼調(diào)試是任何軟件開發(fā)都無可逃避的工作,在Visual Unit的支持下編碼調(diào)試,只是把本來就一定要做的工作改變一下方式,不需要多做什么,就可以大幅提高編程效率和質(zhì)量;另一方面,Visual Unit徹底改變了單元測試難于實(shí)施或成本昂貴的局面,無論團(tuán)隊(duì)中開發(fā)與測試人員的比例是怎么樣的,都可以輕松快捷地實(shí)現(xiàn)徹底的單元測試。 二、高效編碼調(diào)試   任何軟件開發(fā),都離不開編碼調(diào)試。對于稍為復(fù)雜一點(diǎn)的函數(shù),一般來說,編寫幾行代碼,就要執(zhí)行一下,看它們是否按預(yù)想的工作,然后再繼續(xù)寫,寫完后還要將各種可能輸入都執(zhí)行一下。如何執(zhí)行?一般由別的代碼來調(diào)用,也就是說需要驅(qū)動(dòng),驅(qū)動(dòng)通常是在開始編寫函數(shù)實(shí)現(xiàn)代碼之前建立,這樣才能一邊編寫一邊調(diào)試。驅(qū)動(dòng)大致可分為自然驅(qū)動(dòng)和專門驅(qū)動(dòng)。   自然驅(qū)動(dòng):利用項(xiàng)目中已有的代碼作為驅(qū)動(dòng),通常是在被調(diào)試的函數(shù)中加斷點(diǎn),從界面執(zhí)行一個(gè)需要調(diào)用該函數(shù)的功能,調(diào)試器中斷時(shí)就可以調(diào)試了;專門驅(qū)動(dòng):為需要調(diào)試的函數(shù)編寫專門的驅(qū)動(dòng)代碼,通過執(zhí)行驅(qū)動(dòng)代碼來執(zhí)行被調(diào)試函數(shù)。 自然驅(qū)動(dòng)的主要優(yōu)點(diǎn)是不需要其他工作就可以直接調(diào)試,甚至感覺不到需要驅(qū)動(dòng),主要缺點(diǎn)是輸入數(shù)據(jù)通常是公共的,即很多代碼都使用相同的輸入源進(jìn)行調(diào)試,實(shí)際輸入往往是經(jīng)過其他代碼處理后的中間結(jié)果,要針對各種可能輸入都進(jìn)行調(diào)試往往很困難,造成調(diào)試不全面,程序員的思維受到局限,難于做到全面地考慮各種可能輸入。   專門驅(qū)動(dòng)的主要優(yōu)點(diǎn)是輸入數(shù)據(jù)是專門針對于被測試程序,容易做到比較全面,程序員的思維也會(huì)比較全面,對編寫功能齊全的健壯的程序很有好處,要針對某種特定輸入進(jìn)行調(diào)試比較容易,缺點(diǎn)是需要花費(fèi)大量的時(shí)間來編寫驅(qū)動(dòng)代碼。   顯然,自然驅(qū)動(dòng)的主要問題是不全面,代碼錯(cuò)誤較多,專門驅(qū)動(dòng)的主要問題是編寫驅(qū)動(dòng)代碼很費(fèi)時(shí)。有沒有更好的方法,既不需要編寫驅(qū)動(dòng)代碼,又能方便且全面地調(diào)試?有 !這就是自動(dòng)驅(qū)動(dòng),即在Visual Unit的支持下編碼調(diào)試,不但無需費(fèi)時(shí)間寫驅(qū)動(dòng)代碼,更擁有多種獨(dú)特的便利,可以大幅提高編碼調(diào)試的質(zhì)量和效率。   Visual Unit是單元測試工具,但也是高效編程調(diào)試的支持環(huán)境,在Visual Unit的支持下調(diào)試,既全面又省時(shí):   自動(dòng)生成驅(qū)動(dòng)代碼,但又可以方便地設(shè)定調(diào)試輸入;   測試用例編輯器列出全部輸入,可以很方便地檢查是否全面。   除了上述優(yōu)點(diǎn)外,在Visual Unit的支持下調(diào)試,還可以:   可視化地選擇調(diào)試輸入;   調(diào)試過程中還可以切換輸入;   無限制的后退,重復(fù)。   上述僅是免費(fèi)的個(gè)人版的功能,對于企業(yè)版用戶,實(shí)際上大多數(shù)單步調(diào)試都可以省略: 自動(dòng)輸出參數(shù)、成員變量的輸入輸出值,返回值,用戶也可以用簡單的語法輸出任何變量或表達(dá)式的值,這些數(shù)值都是上下文相關(guān)的;   顯示在一個(gè)用例下,程序所執(zhí)行的代碼,可以很方便地查看程序是否按預(yù)想的流程執(zhí)行。   程序無論多復(fù)雜,無非就是執(zhí)行一些代碼,讀寫、計(jì)算一些數(shù)據(jù),因此,上述兩方面信息已完整地描述了程序行為,一眼就能看出程序干了什么,通常可以很快判斷程序是否按預(yù)想的工作并找到出錯(cuò)原因,比單步調(diào)試要快得多。   下面以實(shí)例來進(jìn)一步分析三種調(diào)試方式的優(yōu)缺點(diǎn)。這里所用的示例是范例項(xiàng)目中的CExFunction::ParseOneParameter()函數(shù),這是一個(gè)很普通的函數(shù),讀者也可以隨便拿其他有些復(fù)雜度的代碼來比較。該函數(shù)的功能是解析C++代碼中的一個(gè)參數(shù),原形如下:   PARAMETER* CExFunction::ParseOneParameter(CTokenList& iList);   PARAMETER 是保存一個(gè)參數(shù)對象的結(jié)構(gòu),定義如下:    struct PARAMETER    {    CString type; //參數(shù)類型    CString name; //參數(shù)名    CString defVal; //缺省值    CString array; //如果參數(shù)是數(shù)組,保存[]及[]內(nèi)的文字常量    };      參數(shù)iList是一個(gè)輸入?yún)?shù)(范例的命名規(guī)則是用i表示輸入?yún)?shù)),傳遞由C++代碼中的一個(gè)參數(shù)經(jīng)過詞法分析轉(zhuǎn)換獲得的記號(hào)對象序列,例如參數(shù)int* pi,將轉(zhuǎn)換為三個(gè)記號(hào)對象,分別對應(yīng)于:int, *, pi。該函數(shù)將記號(hào)對象序列解析到一個(gè)PARAMETER結(jié)構(gòu)的指針中,并作為返回值返回。 在這個(gè)示例中,如果要進(jìn)行比較全面的調(diào)試,輸入至少要考慮以下可能:   普通輸入,如int i;   類型中有符號(hào),如int* pi;   類型中有多個(gè)符號(hào),如int*& pi;   模板類,如CList list;   帶缺省值,如int i=0;   數(shù)組,如int ai[10];   類型有多個(gè)單詞,如const unsigned int& i;   缺少參數(shù)名,如const int;   我們在編寫這個(gè)函數(shù)的實(shí)現(xiàn)代碼前,首先建立調(diào)試驅(qū)動(dòng),以例邊編碼邊執(zhí)行調(diào)試。    自然驅(qū)動(dòng)   假設(shè)界面和要調(diào)用這個(gè)函數(shù)的其他代碼都已完成。在函數(shù)的入口處插入斷點(diǎn),以調(diào)試方式運(yùn)行工程,在界面中選擇要生成文檔的工程目錄,點(diǎn)擊"生成文檔",程序中斷時(shí)就可以調(diào)試了。這種方式相信所有程序員都很熟悉,并且很多人都會(huì)認(rèn)為這種方式最省時(shí),但實(shí)際上,這種方式只是開頭省時(shí),當(dāng)你試圖把各個(gè)可能輸入都調(diào)試一遍,就會(huì)發(fā)現(xiàn)它很費(fèi)時(shí):可能輸入通常分散分布于輸入源中(這里的輸入源是代碼文件),如果要比較全面地調(diào)試,通常要整理輸入源,否則幾乎不可能全面地調(diào)試,也就是說,要全面地調(diào)試,仍然要費(fèi)時(shí)間整理輸入,并不能完全依賴自然輸入;   要針對某種輸入進(jìn)行調(diào)試,例如要調(diào)試參數(shù)帶有缺省值的情形,一般通過反復(fù)跟蹤直到想要的輸入出現(xiàn),或者設(shè)置條件斷點(diǎn)攔截所需要輸入,反復(fù)跟蹤當(dāng)然費(fèi)時(shí)不少,設(shè)置條件斷點(diǎn)也是要花時(shí)間的,并且有時(shí)無法滿足需要 ,很多時(shí)候,要針對特殊輸入進(jìn)行調(diào)試都是很大費(fèi)時(shí)的;   由于是公共輸入源,輸入數(shù)據(jù)很難管理,尤其是條件斷點(diǎn)更不可能無限期地保存,以后需要再次調(diào)試時(shí)可能要做很多重復(fù)工作。 如上所述,自然驅(qū)動(dòng)并不省時(shí),不過這種方式的時(shí)間消耗隱藏在調(diào)試過程中,通常不會(huì)引起重視,其實(shí)"隱藏于調(diào)試過程中",其成本更大,因?yàn)榉稚⒘碎_發(fā)人員的注意力,影響思維的連續(xù)性。   自然驅(qū)動(dòng)的更主要問題是不全面,開發(fā)人員常常會(huì)將思維局限于現(xiàn)有的輸入源,導(dǎo)致一些可能輸入根本就沒有考慮到,在本例中,很可能只是試一下解析一兩個(gè)文件,檢查得到的結(jié)果是否正確,如果文件中沒有 帶數(shù)組的參數(shù),那這種輸入很可能就被忽略掉。這種不全面,導(dǎo)致代碼功能不齊,健壯性差,后期測試和維護(hù)成本居高不下,甚至導(dǎo)致項(xiàng)目的失敗,因此,這是看起來高效,實(shí)際上很低效的方式,讀者可以在看完后面兩種方式的介紹后,自 已嘗試并對比一下,可以拿任何有一定復(fù)雜度的代碼編寫來對比,不局限于這里所舉的例子。    專門驅(qū)動(dòng)   專門驅(qū)動(dòng)離單元測試只有一步之遙了,只要在驅(qū)動(dòng)代碼中添加判斷預(yù)期輸出的語句就構(gòu)成了完整的測試代碼,因此,在實(shí)際工作中,采用專門驅(qū)動(dòng)最好是邊編碼邊測試,并使用測試代碼作為調(diào)試驅(qū)動(dòng)。下面是為函數(shù)CExFunction::ParseOneParameter ()編寫的調(diào)試驅(qū)動(dòng)代碼:    {CExFunction* pObj = new CExFunction();    CTokenList iList;    CTokenReader reader;    reader.ReadTokenList(iList, "int i");    PARAMETER* ret = pObj->ParseOneParameter(iList) ;    ASSERT( ret->type == "int" );    ASSERT( ret->name == "i" );    reader.ClearTokenList(iList);    delete pParam;    delete pObj; }      上面的代碼其實(shí)是一個(gè)測試用例的完整代碼,測試代碼通常都是很簡單的,功能無非是使被測試的代碼得于執(zhí)行,被測試代碼通常都涉及到外部數(shù)據(jù),如參數(shù)、成員變量、全局變量什么的,這些數(shù)據(jù)當(dāng)然要設(shè)定初始值,例如,上面的測試用例是將字符串"int i"經(jīng)過CTokenReader對象的ReadTokenList方法轉(zhuǎn)換成CToken對象指針的列表作為參數(shù)iList的輸入。   在實(shí)際工作中,函數(shù)的輸入輸出常常不是簡單的數(shù)據(jù)類型,而是某些對象甚至是對象的集合,本例中,輸入的數(shù)據(jù)就是CToken對象指針的列表。這種情況下,一般借助現(xiàn)有的代碼來生成數(shù)據(jù),通常,這些"現(xiàn)在代碼"都是存在的,因?yàn)榧词共蛔鰷y試,也總有代碼要調(diào)用該函數(shù)的,調(diào)用代碼本來就需要生成相應(yīng)的數(shù)據(jù)。本例中,CTokenReader::ReadTokenList()函數(shù)就是把字符串轉(zhuǎn)換為CToken對象指針的列表。 只要寫完了第一個(gè)測試用例的代碼,更多的用例就簡單了,只要拷貝并對輸入輸出數(shù)據(jù)進(jìn)行修改就行。細(xì)心的讀都可能已注意到,第一個(gè)測試用例的前后加了{(lán)},這是為了多個(gè)測試用例可以使用相同的變量名。   使用這種方法,建立測試代碼通常是很快的。編寫很簡單的函數(shù)時(shí)不需要調(diào)試,當(dāng)然也不需要測試代碼。測試代碼的組織也很簡單:一個(gè)產(chǎn)品工程對應(yīng)一個(gè)測試工程,一個(gè)產(chǎn)品類對應(yīng)一個(gè)測試類,一個(gè)需要測試的產(chǎn)品函數(shù)對應(yīng)一個(gè)測試函數(shù)。測試工程可以加一個(gè)簡單的界面,以便執(zhí)行指定的測試,也可以使用相應(yīng)的工具如 CppUnit。   再回到我們的主題:調(diào)試。有了測試代碼,調(diào)試就簡單了,要調(diào)試某種輸入,只要在相應(yīng)的測試用例中加斷點(diǎn)就行了。使用這種方式,僅就調(diào)試來說,好處也是非常明顯的:   所有輸入在一起列出來,調(diào)試比較全面,程序員的思維也會(huì)比較全面;   要調(diào)試指定的輸入很容易,通常不需要高級(jí)斷點(diǎn),更不需要通過反復(fù)跟蹤來捕捉需要的輸入;   調(diào)試數(shù)據(jù)可以永久保存,避免了以后修改代碼時(shí)的重復(fù)工作。    自動(dòng)驅(qū)動(dòng)   在Visual Unit的支持下編碼調(diào)試,除了兼具自然驅(qū)動(dòng)和專門驅(qū)動(dòng)的優(yōu)點(diǎn)外,還能享受Visual Unit的獨(dú)特殊功能帶來的便利。   首先我們用個(gè)人版來說明,個(gè)人版是免費(fèi)的版本,并且開發(fā)商也提供免費(fèi)的基本技術(shù)支持。   Visual Unit具有豐富的文檔,包括視頻教程,這里不再敘述其基本使用方法。只要選擇要測試(調(diào)試)的類和函數(shù)(如果使用企業(yè)版的IDE插件,會(huì)根據(jù)當(dāng)前文檔和光標(biāo)位置自動(dòng)選擇),VU就會(huì)生成測試代碼,并彈出測試用例編譯器。VU是自動(dòng)生成測試代碼,而不是自動(dòng)生成測試用例,也就是說,輸入輸出數(shù)據(jù)是由用戶指定的,不過VU已經(jīng)生成了輸入輸出數(shù)據(jù)的聲明。下面是本例中VU生成的第一個(gè)測試用例的輸入輸出:   輸入部分: CTokenList iList =   輸出部分: ret ==   這里的“=”和“==”僅僅表示可能需要賦值或判斷輸出,對于基本數(shù)據(jù)類型,可以直接填寫數(shù)值,高級(jí)數(shù)據(jù)類型需要靈活處理(詳細(xì)信息請查看幫助或教程)。只要把輸入輸出改為這樣就完成了第一個(gè)測試用例的建立:   輸入部分:    CTokenList iList = //多余的=會(huì)自動(dòng)刪除    CTokenReader reader    reader.ReadTokenList(iList, "int i")    輸出部分:    ret->type == "int"    ret->name == "i"      更多的測試用例,只要點(diǎn)擊"新建",就會(huì)自動(dòng)拷貝當(dāng)前用例,只要修改輸入輸出就行了。這里沒有涉及到成員變量和變局全量,不過都很簡單的(成員變量用點(diǎn)操作符訪問,全局變量直接訪問),請查看幫助。   可以看出,使用VU建立調(diào)試支持環(huán)境是很快速的:對于第一個(gè)測試用例,輸入輸出比較復(fù)雜時(shí)需要寫少量簡單的代碼,輸入輸出簡單時(shí)直接填寫輸入輸出數(shù)值,其他測試用例只需點(diǎn)擊一個(gè)按鈕拷貝現(xiàn)有測試用例并修改輸入輸出就行,可以選擇相近的用例來生成新的用例,這樣通常只需要修改一兩個(gè)數(shù)據(jù)就可以得到想要的用例。   那么,還可以得到哪些好處呢?   方便地進(jìn)入調(diào)式:在被調(diào)試函數(shù)的入口加斷點(diǎn),并調(diào)試測試工程即可進(jìn)入調(diào)試;   方便地選擇輸入:在測試用例編輯器中輕點(diǎn)鼠標(biāo)即可指定要調(diào)試的輸入,如果執(zhí)行了測試,只要點(diǎn)擊出錯(cuò)的測試,就會(huì)自動(dòng)選擇相應(yīng)的輸入;   方便地切換輸入:調(diào)試過程中,不需要退出調(diào)試,就可以切換到其他輸入:只要在測試用例編輯器中選擇另一個(gè)測試用例,用調(diào)試器的"執(zhí)行到光標(biāo)所在行"命令回到函數(shù)入口,即可切換到新的輸入;   無限制后退重復(fù):用調(diào)試器的"執(zhí)行到光標(biāo)所在行"命令可以自由地后退和重復(fù)執(zhí)行,其實(shí)現(xiàn)的原理是"重來",后退時(shí)相關(guān)數(shù)據(jù)也會(huì)"還原",感覺上是真正的"后退",這個(gè)奇特而有用的功能是VU生成的測試代碼自動(dòng)實(shí)現(xiàn)的。   上述是免費(fèi)的個(gè)人版所具有功能,VU企業(yè)版除了具有這些功能外,還具有"描述程序行為"的功能:   自動(dòng)輸出參數(shù)、成員變量的輸入輸出值,返回值,用戶也可以用簡單的語法輸出任何變量或表達(dá)式的值。這些數(shù)值都是上下文相關(guān)的,也就是說,同一個(gè)用例的相關(guān)值放在一起;   顯示在任一個(gè)用例下程序所執(zhí)行的代碼,可以很方便地查看程序是否按預(yù)想的流程執(zhí)行。 程序無論多復(fù)雜,無非就是執(zhí)行一些代碼,讀寫、計(jì)算一些數(shù)據(jù),因此,上述兩方面信息已完整地描述了程序行為,很容易看出"程序干了什么"。這個(gè)功能大幅度地提高了開發(fā)人員的工作效率:   幫助整理、驗(yàn)證編程思路:寫幾行代碼,就可以看看"程序干了什么",輕松判斷"現(xiàn)在所寫的對不對",也比較容易想清楚"接下來要怎么寫"。快速找出程序錯(cuò)誤:根據(jù)輸入輸出數(shù)據(jù)和所執(zhí)行的代碼,通常可以很快判斷程序是否按預(yù)期工作并找到出錯(cuò)原因,比單步調(diào)試要快得多。編程的時(shí)間消耗主要不在于敲鍵盤,而在于編程思路和調(diào)試,VU企業(yè)版可謂"對癥下藥",在這兩方面大量提高工作效率。   以上所述,都是針對軟件開發(fā)過程中無可逃避的工作:編碼調(diào)試。僅從時(shí)間上來說,對于編寫調(diào)試有一定復(fù)雜度的程序,使用專門驅(qū)動(dòng),可能比自然驅(qū)動(dòng)多費(fèi)一點(diǎn)時(shí)間,但也是完全合算的,至于自動(dòng)驅(qū)動(dòng),如果使用VU個(gè)人版,大概能省時(shí)10%,如果使用企業(yè)版,則可以省時(shí)20-50%!讀者可以自行嘗試比較一下。是否省時(shí)還不是最重要的,更高的價(jià)值在于:使用專門驅(qū)動(dòng)或自動(dòng)驅(qū)動(dòng)編碼調(diào)試,實(shí)際上也已經(jīng)把令人望而生畏的單元測試工作完成了一半,并清除了實(shí)施單元測試的最主要障礙。 三、實(shí)現(xiàn)徹底單元測試   是什么使單元測試難于實(shí)施?首先是代碼的可測性。可測性是什么?如果一個(gè)類具有基本的可測性,那么把它加入到另一個(gè)工程后(當(dāng)然有關(guān)聯(lián)的文件也要加入)能夠通過編譯,這其實(shí)是很低的要求,但對于一個(gè)有一定規(guī)模的項(xiàng)目,如果開發(fā)調(diào)試時(shí)使用自然驅(qū)動(dòng),在完成編碼后才進(jìn)行單元測試,那么通常都不具有可測性,因?yàn)殚_發(fā)人員常常在無意之中使代碼之間產(chǎn)生了不當(dāng)耦合,這些不當(dāng)耦合累積起來,會(huì)使整個(gè)項(xiàng)目的代碼糾纏在一起,造成難于測試。   使單元測試難于實(shí)施的另一個(gè)方面是建立測試用例。在本例中,如果由不熟悉代碼的測試人員建立測試用例,那么他很可能不知道如何生成CToken對象 指針的列表。   如果邊開發(fā)邊使用專門驅(qū)動(dòng)(測試代碼放在另一個(gè)工程中)或自動(dòng)驅(qū)動(dòng)調(diào)試,那么一旦出現(xiàn)影響可測性的不當(dāng)耦合就會(huì)及時(shí)發(fā)現(xiàn)及時(shí)解決,保證了代碼的可測性,另一方面,由于至少建立了一個(gè)測試用例,測試人員建立其他用例時(shí)只要修改一下輸入輸出數(shù)據(jù),從而大大降低建立測試用例的難度。總之,使用專門驅(qū)動(dòng)或自動(dòng)驅(qū)動(dòng)調(diào)試,在不增加開發(fā)工作量的同時(shí),已經(jīng)為單元測試打一下了堅(jiān)實(shí)的基礎(chǔ)。   范例項(xiàng)目V0.1處于這樣一個(gè)階段:剛剛完成代碼編寫,并未完成單元測試,現(xiàn)有的多數(shù)測試用例都是編碼時(shí)用于調(diào)試的。在此基礎(chǔ)上,單元測試由誰做,難度都不大。VU的典型應(yīng)用是通過三個(gè) 階段來完成針對一個(gè)函數(shù)的徹底的測試:   1)基本功能測試:測試代碼的基本功能;   2)完成白盒覆蓋:在現(xiàn)有用例的基礎(chǔ)上,使用測試用例設(shè)計(jì)器為未覆蓋的語句、條件、分支、路徑設(shè)計(jì)測試用例,達(dá)到100%語句、條件、分支、路徑覆蓋;   3)執(zhí)行自動(dòng)邊界測試捕捉意料之外的錯(cuò)誤。   以上三階段可以由不同人員在不同時(shí)間完成,團(tuán)隊(duì)可以根據(jù)實(shí)際情況做出靈活安排,下面是一個(gè)典型的開發(fā)測試流程。   1)開發(fā)人員邊開發(fā)邊使用VU調(diào)試測試,完成基本功能測試。在VU的支持下開發(fā)調(diào)試,可以大幅提高開發(fā)效率,絕不會(huì)影響開發(fā)進(jìn)度。也許讀者會(huì)認(rèn)為,開發(fā)人員沒有時(shí)間去設(shè)計(jì)測試用例,其實(shí)這是一種誤解,開發(fā)人員寫代碼時(shí)肯定要想清楚代碼的功能并且要使用基本的輸入進(jìn)行調(diào)試,這些就是基本的測試用例,實(shí)際上不需要多做什么。開發(fā)人員提交代碼同時(shí)提交測試代碼和測試報(bào)告。如果項(xiàng)目已完成或部分完成編碼,也建議先由程序員首先對重要代碼進(jìn)行基本的功能測試。   2)測試人員檢查基本測試用例是否符合設(shè)計(jì),并在此基礎(chǔ)上完成白盒覆蓋和邊界測試。由于有了初步的測試,保證了代碼可測性,不可能產(chǎn)生因?yàn)椴划?dāng)耦合造成難于測試的狀況;在現(xiàn)有用例的基礎(chǔ)上,使用測試用例設(shè)計(jì)器找出遺漏用例也不會(huì)有太大障礙,這就使測試人員的工作易于進(jìn)行。測試人員只需要提交更新過的測試代碼和測試報(bào)告,不需要另外記錄測出的問題。   3)開發(fā)人員下載新的測試代碼和測試報(bào)告,執(zhí)行整體測試,然后針對報(bào)告了錯(cuò)誤的函數(shù)執(zhí)行函數(shù)測試以獲取詳細(xì)信息,必要時(shí)進(jìn)行調(diào)試,找出錯(cuò)誤,修改代碼,使所有測試通過,再次提交產(chǎn)品代碼和測試報(bào)告。   4)測試人員再次執(zhí)行整體測試,驗(yàn)證所有的測試均已通過。   以上流程是動(dòng)態(tài)和反復(fù)的,并不是編碼完成后再單元測試。開發(fā)人員寫完一個(gè)類后即可提交代碼由測試人員完成白盒覆蓋和邊界測試。另外,團(tuán)隊(duì)可以根據(jù)開發(fā)與測試人員的比例調(diào)整工作份額,如果團(tuán)隊(duì)沒有測試人員,那么由開發(fā)人員完成全部單元測試也是可行的。   徹底的單元測試對于軟件開發(fā)來說,其價(jià)值是難于估量的:除了保證局部代碼的質(zhì)量外,有了單元測試,任何時(shí)候修改代碼后都可以通過回歸測試來自動(dòng)檢查修改是否引入錯(cuò)誤,這就使開發(fā)過程可以適應(yīng)頻繁變化的需求,系統(tǒng)分析、概要設(shè)計(jì)和詳細(xì)設(shè)計(jì)都可以做得簡單一些,也更能適應(yīng)螺旋式開發(fā)過程,以后的維護(hù)升級(jí)成本也會(huì)大幅降低,同時(shí),高質(zhì)量的代碼使集成測試和系統(tǒng)測試的工作量降低很多(實(shí)際上單元測試已包含了大部分的集成測試),發(fā)現(xiàn)問題后的修改也會(huì)高效得多。總之,要提高軟件開發(fā)質(zhì)量、降低軟件開發(fā)成本,最有效的改進(jìn)就是進(jìn)行徹底的單元測試,如果不進(jìn)行單元測試,任何流程改進(jìn)都無法保證產(chǎn)品質(zhì)量,因?yàn)椋绦蚴冀K是由代碼構(gòu)成的,代碼的質(zhì)量沒有保證,軟件的質(zhì)量拿什么來保證?單元測試并不排斥其他過程改進(jìn),相反,單元測試對開發(fā)流程中的所有環(huán)節(jié)幾乎都有促進(jìn)作用。   下邊再談?wù)勱P(guān)于白盒覆蓋的話題。使用VU實(shí)施單元測試,100%的語句、條件、分支覆蓋通常都是很容易的,路徑覆蓋有時(shí)候會(huì)很難,例如,我們所舉的例子, CExFunction::ParseOneParameter (),有九十多條路徑,要覆蓋似乎不現(xiàn)實(shí)或沒必要,這種狀況通常是設(shè)計(jì)不合理造成的,例如,CExFunction:: ParseOneParameter ()函數(shù)的代碼分為三塊:1、解析缺省值,2、解析數(shù)組,3、解析類型和參數(shù)名,前兩塊解析了缺省值和數(shù)組后把相應(yīng)的Token從列表中刪除,這樣的話,第3塊與前兩塊是沒有邏輯關(guān)系的,但是,這3塊代碼會(huì)組合出很多路徑,沒有邏輯關(guān)系的代碼所組合出來的路徑是沒有意義的,這些代碼具有"高耦合低內(nèi)聚"的特征,不應(yīng)該放在一個(gè)函數(shù)中。范例中另外寫了一個(gè)函數(shù):CExFunction::ParseOneParameter2(),把以上三塊代碼分別獨(dú)立出來自成一個(gè)函數(shù),這樣每個(gè)函數(shù)都能完成100%的路徑覆蓋,重構(gòu)后的代碼既易于測試,也易于維護(hù)。范例中有大量類似的函數(shù),甚至有超過200行的函數(shù),這是為了檢驗(yàn)VU的適應(yīng)能力,以后的版本是會(huì)進(jìn)行重構(gòu)。我們建議程序員完成編碼后,檢查一下路徑數(shù)量,如果路徑很多,代碼很可能需要分拆,合理的路徑數(shù)量應(yīng)該是等價(jià)類數(shù)量的一至兩倍。另外,從邏輯結(jié)構(gòu)圖也可以看出來:圖中有兩個(gè)或兩個(gè)以上串聯(lián)的復(fù)雜分支結(jié)構(gòu),往往表示代碼的結(jié)構(gòu)有問題。   VU的邏輯結(jié)構(gòu)圖具有屏蔽對象的功能,因此,遇到上述情形時(shí)可以通過交替屏蔽部分分支結(jié)構(gòu)的方式來實(shí)現(xiàn)路徑覆蓋,但這不是我們推薦的方式,因?yàn)樗m然可以保證測試的完整性,但并沒有改進(jìn)代碼的結(jié)構(gòu)。   關(guān)于單元測試和范例項(xiàng)目,還有很多值得敘述的話題,例如內(nèi)存泄漏測試以及一些復(fù)雜問題的處理等等,這里暫且不談。最后談?wù)勔淹瓿删幋a的項(xiàng)目的單元測試。對于已完成編碼的項(xiàng)目,最好先由開發(fā)人員"去耦合",方法是將代碼文件從底層向上排列,按順序依次將文件加入到另一個(gè)工程并編譯,如果產(chǎn)生編譯錯(cuò)誤,則想辦法消除編譯錯(cuò)誤 ,VU提供了文件排序工具,具體的使用方法請查閱幫助中《測試舊工程》部分。完成“去耦合”后,由開發(fā)人員對自己編寫的代碼完成基本功能測試,測試人員完成白盒覆蓋和邊界測試。對于編碼過程中使用自然驅(qū)動(dòng)調(diào)試的已完成編寫的代碼,完全由測試部門進(jìn)行單元測試通常是很難的。 來自:http://www.rjzl.gov.cn/news.asp?id=2351
posted on 2009-03-05 17:05 thronds 閱讀(358) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 工程管理
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美三级伦理| 亚洲乱码国产乱码精品精天堂| 欧美午夜视频一区二区| 久久久久久网| 亚洲欧美视频一区| 亚洲中字黄色| 亚洲欧美国内爽妇网| 亚洲伊人久久综合| 亚洲一区二区伦理| 欧美一区二区三区日韩视频| 久久激情五月丁香伊人| 暖暖成人免费视频| 欧美三级乱码| 国内成人精品2018免费看| 日韩视频在线观看国产| 亚洲欧美日韩视频二区| 久久伊伊香蕉| 亚洲午夜视频| 免费不卡视频| 国产精品区一区二区三区| 尤物视频一区二区| 亚洲欧美日韩精品综合在线观看| 免费永久网站黄欧美| 一本色道久久88综合亚洲精品ⅰ | 久久黄金**| 亚洲第一在线视频| 中文精品在线| 另类图片国产| 国产老女人精品毛片久久| 最近看过的日韩成人| 久久av免费一区| 夜夜嗨av色一区二区不卡| 久久丁香综合五月国产三级网站| 欧美日韩精品一区视频| 亚洲国产高清在线观看视频| 午夜在线一区| 一本一道久久综合狠狠老精东影业 | 狠狠网亚洲精品| 小黄鸭视频精品导航| 亚洲精品在线视频观看| 老牛国产精品一区的观看方式| 国产日韩精品在线播放| 亚洲天堂第二页| 亚洲精品系列| 欧美sm视频| 亚洲电影在线免费观看| 久久在线观看视频| 国产精品午夜春色av| 欧美极品一区| 在线观看亚洲视频| 久久精品盗摄| 欧美一二三视频| 国产精品一区二区久久精品| 亚洲午夜精品在线| 日韩视频一区二区在线观看| 欧美激情在线| 亚洲成色www久久网站| 日韩一区二区精品视频| 欧美成人在线影院| 久久综合九色综合网站| 亚洲国产成人在线播放| 蜜臀99久久精品久久久久久软件| 久久福利一区| 一区二区三区自拍| 欧美成人精品在线视频| 欧美成人高清| 中文av字幕一区| 亚洲一本视频| 国产亚洲一区二区在线观看| 久久噜噜亚洲综合| 欧美不卡在线视频| 9人人澡人人爽人人精品| 正在播放亚洲| 黄色一区二区三区| 亚洲国产美女| 国产精品v日韩精品v欧美精品网站| 亚洲免费在线视频| 欧美影院在线播放| 亚洲欧洲日韩在线| 一区二区三区四区精品| 国产日韩一区欧美| 麻豆av一区二区三区| 欧美人在线视频| 欧美一区二区三区成人| 久久久久久久久久久一区 | 亚洲制服av| 久久狠狠一本精品综合网| 亚洲黄色成人| 亚洲免费网址| 亚洲日本va午夜在线电影| 一区二区日本视频| 狠狠色综合播放一区二区| 亚洲人在线视频| 国产日韩欧美综合一区| 最新国产成人在线观看| 国产精品亚洲综合久久| 欧美国产日本高清在线| 国产伦精品一区二区三区四区免费 | 亚洲激情视频在线| 国产日韩专区| 一本色道久久综合狠狠躁篇的优点 | 欧美日韩亚洲91| 亚洲美女在线观看| 亚洲综合成人婷婷小说| 亚洲大胆女人| 亚洲小说春色综合另类电影| **性色生活片久久毛片| 亚洲五月六月| 亚洲乱码国产乱码精品精天堂| 亚洲欧美www| 国产精品99久久久久久久vr| 久久婷婷亚洲| 久久久久9999亚洲精品| 国产精品区一区二区三| 亚洲伦理一区| 亚洲精品免费在线播放| 久久久久青草大香线综合精品| 亚洲女同性videos| 欧美精品自拍偷拍动漫精品| 男人天堂欧美日韩| 黄色精品一区二区| 欧美中文在线观看| 欧美一级免费视频| 国产精品久久午夜| 一区二区三区久久网| 一区二区久久久久久| 欧美高清在线精品一区| 欧美高清在线观看| 在线欧美日韩国产| 久久久亚洲一区| 蜜臀久久99精品久久久久久9 | 国产一区在线免费观看| 一区二区三区|亚洲午夜| 日韩视频一区| 欧美精品日韩精品| 亚洲精品123区| 亚洲国产女人aaa毛片在线| 久久精品国产久精国产一老狼| 久久精品国产99国产精品| 国产精品亚洲综合色区韩国| 亚洲男人影院| 久久久精品国产免大香伊 | 亚洲欧美在线播放| 国产精品国产三级国产专区53 | 新67194成人永久网站| 欧美资源在线| 黄色亚洲在线| 免费在线欧美视频| 亚洲人成人99网站| 亚洲自拍另类| 国产亚洲欧美日韩在线一区| 亚洲精选大片| 先锋影音一区二区三区| 夜夜精品视频| 欧美性事免费在线观看| 亚洲视频在线观看一区| 新片速递亚洲合集欧美合集| 国语精品中文字幕| 欧美大片免费观看在线观看网站推荐| 亚洲国产精品成人精品| 亚洲综合二区| 黄色成人精品网站| 欧美精品一区二区久久婷婷| 一本大道久久a久久综合婷婷| 久久精品国产999大香线蕉| 最新国产成人在线观看 | 亚洲黄色在线| 欧美色一级片| 久久精品国产99精品国产亚洲性色 | 国产精品99久久不卡二区| 久久久精品国产免大香伊| 亚洲人体影院| 国产日韩亚洲欧美| 欧美国产一区二区在线观看| 午夜精品久久久久久久99水蜜桃 | 在线观看日韩国产| 国产精品成人av性教育| 久久久久久久综合狠狠综合| 夜夜精品视频一区二区| 免费亚洲电影在线| 亚洲男女自偷自拍图片另类| 在线日韩中文| 国产日韩欧美不卡在线| 欧美日韩国产在线播放| 久久久久久久久久久久久女国产乱| 一区二区三区www| 亚洲国产视频一区| 老司机免费视频一区二区三区| 亚洲午夜av电影| 亚洲精品一区久久久久久| 狠狠色伊人亚洲综合成人| 国产精品免费一区二区三区在线观看 | 久久躁狠狠躁夜夜爽| 午夜日韩视频| 亚洲视频视频在线| 日韩视频中文字幕| 亚洲经典三级| 91久久精品国产91性色tv| 伊人成人网在线看| 狠狠v欧美v日韩v亚洲ⅴ|