程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 高效開發與徹底測試

高效開發與徹底測試

編輯:關於VC++

一、“千般路”與“磨豆腐”

很久以前聽一個故事:從前有個小伙子,少時有大志,長大後卻無好營生,開了個豆腐作坊,每天磨豆腐累得腰酸背疼。每到夜深人靜,小伙子輾轉反側,總想找條更好的“事業之路”,可是想過千百條、嘗試過幾十條路,都走不通。夜不成寢,白天干活更累,小伙子不由慨歎:“晚上想過千般路,白天還得磨豆腐”。

不久以前看過一篇文章:《CMM欺騙了中國的軟件業》,內容是對CMM熱的反思。CMM當然不會主動欺騙人,實際上是我們的軟件業自己欺騙自己。我們從來不缺少“某某模式”,“面向某某”,“某某認證”等等聽起來美妙無比的東西,問題是實際的研發過程中能做得到碼?現實是殘酷的,美妙的概念漫天飛舞,開發過程仍然是作坊式的,正是:“晚上想過千般路,白天還得磨豆腐”。

中國的故事通常都有圓滿的結局,現在接著說“磨豆腐”的故事。過了很長時間,小伙子終於面對現實,不再沉迷於不切實際的空想,用心磨好豆腐,閒時琢磨些個竅門,慢慢地,他的豆腐質量越來越好,每天產量也越來越多,作坊越開越大,成了遠近聞名的“豆腐老板”,後來,他做起了別的生意,發現年輕時的空想,其實很多都是可行的,因為現在“能力”和“財力”都不同了。

再說軟件開發。我們不反對任何理論、技術、方法、模式等等,但第一,您的企業或團隊做得到嗎?不要做“如果開發時間延長一倍,就可以做到”之類毫無意義的假設。第二,做了真的有效益嗎?效益是指扣除成本之後的收益。如果不具備這兩點,那麼還是不要整天想著“千般路”,首先想想如何好好的“磨豆腐”吧。

對於所有軟件開發來說,代碼編寫都是無可逃避的“磨豆腐”。改進代碼編寫工作,高率效低成本地開發出高質量的代碼,對於軟件產品能否在激烈的競爭中勝出,對於軟件企業的生存和發展,都具有重要的現實意義。

本文是Visual Unit應用的范例項目C++代碼文檔生成器的主題文檔,敘述的正是改進代碼編寫工作的方法和工具,所有內容均經過實戰檢驗,具有"可行"和"效益"兩個特征,"可行"是指較低門檻或沒有門檻,憑現有條件即可實施;"效益"是指能產生立竿見影的效果。

本文所援引的范例項目,模擬最糟糕的開發團隊,最混亂的開發流程:由很少寫代碼的測試和預研部門開發,人員不固定,時間也不固定,誰有空就寫上一些;沒有設計,沒有文檔,基至也不在代碼文件中保存編碼人員的信息,成員完全依賴於閱讀代碼和測試用例來理解其他成員寫的代碼;除了簡單的命名規則外,沒有其他規范,甚至連一個函數原則上不能超過50行之類的基本規范也沒有(范例中有超過200行的函數CMacro::Unwind(),一萬多條路徑)。 任何開發團隊和開發流程都會好於范例項目的開發團隊和開發流程,因此,范例所展示的方法和工具,具有"廣泛可行性"。

本文介紹如何進行高效編碼調試和實現徹底的單元測試。編碼調試是任何軟件開發都無可逃避的工作,在Visual Unit的支持下編碼調試,只是把本來就一定要做的工作改變一下方式,不需要多做什麼,就可以大幅提高編程效率和質量;另一方面,Visual Unit徹底改變了單元測試難於實施或成本昂貴的局面,無論團隊中開發與測試人員的比例是怎麼樣的,都可以輕松快捷地實現徹底的單元測試。

二、高效編碼調試

任何軟件開發,都離不開編碼調試。對於稍為復雜一點的函數,一般來說,編寫幾行代碼,就要執行一下,看它們是否按預想的工作,然後再繼續寫,寫完後還要將各種可能輸入都執行一下。如何執行?一般由別的代碼來調用,也就是說需要驅動,驅動通常是在開始編寫函數實現代碼之前建立,這樣才能一邊編寫一邊調試。驅動大致可分為自然驅動和專門驅動。

自然驅動:利用項目中已有的代碼作為驅動,通常是在被調試的函數中加斷點,從界面執行一個需要調用該函數的功能,調試器中斷時就可以調試了;專門驅動:為需要調試的函數編寫專門的驅動代碼,通過執行驅動代碼來執行被調試函數。

自然驅動的主要優點是不需要其他工作就可以直接調試,甚至感覺不到需要驅動,主要缺點是輸入數據通常是公共的,即很多代碼都使用相同的輸入源進行調試,實際輸入往往是經過其他代碼處理後的中間結果,要針對各種可能輸入都進行調試往往很困難,造成調試不全面,程序員的思維受到局限,難於做到全面地考慮各種可能輸入。

專門驅動的主要優點是輸入數據是專門針對於被測試程序,容易做到比較全面,程序員的思維也會比較全面,對編寫功能齊全的健壯的程序很有好處,要針對某種特定輸入進行調試比較容易,缺點是需要花費大量的時間來編寫驅動代碼。

顯然,自然驅動的主要問題是不全面,代碼錯誤較多,專門驅動的主要問題是編寫驅動代碼很費時。有沒有更好的方法,既不需要編寫驅動代碼,又能方便且全面地調試?有 !這就是自動驅動,即在Visual Unit的支持下編碼調試,不但無需費時間寫驅動代碼,更擁有多種獨特的便利,可以大幅提高編碼調試的質量和效率。

Visual Unit是單元測試工具,但也是高效編程調試的支持環境,在Visual Unit的支持下調試,既全面又省時:

自動生成驅動代碼,但又可以方便地設定調試輸入;

測試用例編輯器列出全部輸入,可以很方便地檢查是否全面。

除了上述優點外,在Visual Unit的支持下調試,還可以:

可視化地選擇調試輸入;

調試過程中還可以切換輸入;

無限制的後退,重復。

上述僅是免費的個人版的功能,對於企業版用戶,實際上大多數單步調試都可以省略:

自動輸出參數、成員變量的輸入輸出值,返回值,用戶也可以用簡單的語法輸出任何變量或表達式的值,這些數值都是上下文相關的;

顯示在一個用例下,程序所執行的代碼,可以很方便地查看程序是否按預想的流程執行。

程序無論多復雜,無非就是執行一些代碼,讀寫、計算一些數據,因此,上述兩方面信息已完整地描述了程序行為,一眼就能看出程序干了什麼,通常可以很快判斷程序是否按預想的工作並找到出錯原因,比單步調試要快得多。

下面以實例來進一步分析三種調試方式的優缺點。這裡所用的示例是范例項目中的CExFunction::ParseOneParameter()函數,這是一個很普通的函數,讀者也可以隨便拿其他有些復雜度的代碼來比較。該函數的功能是解析C++代碼中的一個參數,原形如下:

PARAMETER* CExFunction::ParseOneParameter(CTokenList& iList);

PARAMETER 是保存一個參數對象的結構,定義如下:

struct PARAMETER
{
CString type; //參數類型
CString name; //參數名
CString defVal; //缺省值
CString array; //如果參數是數組,保存[]及[]內的文字常量
};

參數iList是一個輸入參數(范例的命名規則是用i表示輸入參數),傳遞由C++代碼中的一個參數經過詞法分析轉換獲得的記號對象序列,例如參數int* pi,將轉換為三個記號對象,分別對應於:int, *, pi。該函數將記號對象序列解析到一個PARAMETER結構的指針中,並作為返回值返回。

在這個示例中,如果要進行比較全面的調試,輸入至少要考慮以下可能:

普通輸入,如int i;

類型中有符號,如int* pi;

類型中有多個符號,如int*& pi;

模板類,如CList<int, int> list;

帶缺省值,如int i=0;

數組,如int ai[10];

類型有多個單詞,如const unsigned int& i;

缺少參數名,如const int;

我們在編寫這個函數的實現代碼前,首先建立調試驅動,以例邊編碼邊執行調試。

自然驅動

假設界面和要調用這個函數的其他代碼都已完成。在函數的入口處插入斷點,以調試方式運行工程,在界面中選擇要生成文檔的工程目錄,點擊"生成文檔",程序中斷時就可以調試了。這種方式相信所有程序員都很熟悉,並且很多人都會認為這種方式最省時,但實際上,這種方式只是開頭省時,當你試圖把各個可能輸入都調試一遍,就會發現它很費時:可能輸入通常分散分布於輸入源中(這裡的輸入源是代碼文件),如果要比較全面地調試,通常要整理輸入源,否則幾乎不可能全面地調試,也就是說,要全面地調試,仍然要費時間整理輸入,並不能完全依賴自然輸入;

要針對某種輸入進行調試,例如要調試參數帶有缺省值的情形,一般通過反復跟蹤直到想要的輸入出現,或者設置條件斷點攔截所需要輸入,反復跟蹤當然費時不少,設置條件斷點也是要花時間的,並且有時無法滿足需要 ,很多時候,要針對特殊輸入進行調試都是很大費時的;

由於是公共輸入源,輸入數據很難管理,尤其是條件斷點更不可能無限期地保存,以後需要再次調試時可能要做很多重復工作。

如上所述,自然驅動並不省時,不過這種方式的時間消耗隱藏在調試過程中,通常不會引起重視,其實"隱藏於調試過程中",其成本更大,因為分散了開發人員的注意力,影響思維的連續性。

自然驅動的更主要問題是不全面,開發人員常常會將思維局限於現有的輸入源,導致一些可能輸入根本就沒有考慮到,在本例中,很可能只是試一下解析一兩個文件,檢查得到的結果是否正確,如果文件中沒有 帶數組的參數,那這種輸入很可能就被忽略掉。這種不全面,導致代碼功能不齊,健壯性差,後期測試和維護成本居高不下,甚至導致項目的失敗,因此,這是看起來高效,實際上很低效的方式,讀者可以在看完後面兩種方式的介紹後,自 已嘗試並對比一下,可以拿任何有一定復雜度的代碼編寫來對比,不局限於這裡所舉的例子。

專門驅動

專門驅動離單元測試只有一步之遙了,只要在驅動代碼中添加判斷預期輸出的語句就構成了完整的測試代碼,因此,在實際工作中,采用專門驅動最好是邊編碼邊測試,並使用測試代碼作為調試驅動。下面是為函數CExFunction::ParseOneParameter ()編寫的調試驅動代碼:

{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;}

上面的代碼其實是一個測試用例的完整代碼,測試代碼通常都是很簡單的,功能無非是使被測試的代碼得於執行,被測試代碼通常都涉及到外部數據,如參數、成員變量、全局變量什麼的,這些數據當然要設定初始值,例如,上面的測試用例是將字符串"int i"經過CTokenReader對象的ReadTokenList方法轉換成CToken對象指針的列表作為參數iList的輸入。

在實際工作中,函數的輸入輸出常常不是簡單的數據類型,而是某些對象甚至是對象的集合,本例中,輸入的數據就是CToken對象 指針的列表。這種情況下, 一般借助現有的代碼來生成數據,通常,這些"現在代碼"都是存在的,因為即使不做測試,也總有代碼要調用該函數的,調用代碼本來就需要生成相應的數據。本例中,CTokenReader::ReadTokenList()函數就是把字符串轉換為CToken對象指針的列表。

只要寫完了第一個測試用例的代碼,更多的用例就簡單了,只要拷貝並對輸入輸出數據進行修改就行。細心的讀都可能已注意到,第一個測試用例的前後加了{},這是為了多個測試用例可以使用相同的變量名。

使用這種方法,建立測試代碼通常是很快的。編寫很簡單的函數時不需要調試,當然也不需要測試代碼。測試代碼的組織也很簡單:一個產品工程對應一個測試工程,一個產品類對應一個測試類,一個需要測試的產品函數對應一個測試函數。測試工程可以加一個簡單的界面,以便執行指定的測試,也可以使用相應的工具如CppUnit。

再回到我們的主題:調試。有了測試代碼,調試就簡單了,要調試某種輸入,只要在相應的測試用例中加斷點就行了。使用這種方式,僅就調試來說,好處也是非常明顯的:

所有輸入在一起列出來,調試比較全面,程序員的思維也會比較全面;

要調試指定的輸入很容易,通常不需要高級斷點,更不需要通過反復跟蹤來捕捉需要的輸入;

調試數據可以永久保存,避免了以後修改代碼時的重復工作。

自動驅動

在Visual Unit的支持下編碼調試,除了兼具自然驅動和專門驅動的優點外,還能享受Visual Unit的獨特殊功能帶來的便利。

首先我們用個人版來說明,個人版是免費的版本,並且開發商也提供免費的基本技術支持。

Visual Unit具有豐富的文檔,包括視頻教程,這裡不再敘述其基本使用方法。只要選擇要測試(調試)的類和函數(如果使用企業版的IDE插件,會根據當前文檔和光標位置自動選擇),VU就會生成測試代碼,並彈出測試用例編譯器。VU是自動生成測試代碼,而不是自動生成測試用例,也就是說,輸入輸出數據是由用戶指定的,不過VU已經生成了輸入輸出數據的聲明。下面是本例中VU生成的第一個測試用例的輸入輸出:

輸入部分:

CTokenList iList =

輸出部分:

ret ==

這裡的“=”和“==”僅僅表示可能需要賦值或判斷輸出,對於基本數據類型,可以直接填寫數值,高級數據類型需要靈活處理(詳細信息請查看幫助或教程)。只要把輸入輸出改為這樣就完成了第一個測試用例的建立:

輸入部分:

CTokenList iList = //多余的=會自動刪除
CTokenReader reader
reader.ReadTokenList(iList, "int i")

輸出部分:

ret->type == "int"
ret->name == "i"

更多的測試用例,只要點擊"新建",就會自動拷貝當前用例,只要修改輸入輸出就行了。這裡沒有涉及到成員變量和變局全量,不過都很簡單的(成員變量用點操作符訪問,全局變量直接訪問),請查看幫助。

可以看出,使用VU建立調試支持環境是很快速的:對於第一個測試用例,輸入輸出比較復雜時需要寫少量簡單的代碼,輸入輸出簡單時直接填寫輸入輸出數值,其他測試用例只需點擊一個按鈕拷貝現有測試用例並修改輸入輸出就行,可以選擇相近的用例來生成新的用例,這樣通常只需要修改一兩個數據就可以得到想要的用例。

那麼,還可以得到哪些好處呢?

方便地進入調式:在被調試函數的入口加斷點,並調試測試工程即可進入調試;

方便地選擇輸入:在測試用例編輯器中輕點鼠標即可指定要調試的輸入,如果執行了測試,只要點擊出錯的測試,就會自動選擇相應的輸入;

方便地切換輸入:調試過程中,不需要退出調試,就可以切換到其他輸入:只要在測試用例編輯器中選擇另一個測試用例,用調試器的"執行到光標所在行"命令回到函數入口,即可切換到新的輸入;

無限制後退重復:用調試器的"執行到光標所在行"命令可以自由地後退和重復執行,其實現的原理是"重來",後退時相關數據也會"還原",感覺上是真正的"後退",這個奇特而有用的功能是VU生成的測試代碼自動實現的。

上述是免費的個人版所具有功能,VU企業版除了具有這些功能外,還具有"描述程序行為"的功能:

自動輸出參數、成員變量的輸入輸出值,返回值,用戶也可以用簡單的語法輸出任何變量或表達式的值。這些數值都是上下文相關的,也就是說,同一個用例的相關值放在一起;

顯示在任一個用例下程序所執行的代碼,可以很方便地查看程序是否按預想的流程執行。

程序無論多復雜,無非就是執行一些代碼,讀寫、計算一些數據,因此,上述兩方面信息已完整地描述了程序行為,很容易看出"程序干了什麼"。這個功能大幅度地提高了開發人員的工作效率:

幫助整理、驗證編程思路:寫幾行代碼,就可以看看"程序干了什麼",輕松判斷"現在所寫的對不對",也比較容易想清楚"接下來要怎麼寫"。

快速找出程序錯誤:根據輸入輸出數據和所執行的代碼,通常可以很快判斷程序是否按預期工作並找到出錯原因,比單步調試要快得多。

編程的時間消耗主要不在於敲鍵盤,而在於編程思路和調試,VU企業版可謂"對症下藥",在這兩方面大量提高工作效率。

以上所述,都是針對軟件開發過程中無可逃避的工作:編碼調試。僅從時間上來說,對於編寫調試有一定復雜度的程序,使用專門驅動,可能比自然驅動多費一點時間,但也是完全合算的,至於自動驅動,如果使用VU個人版,大概能省時10%,如果使用企業版,則可以省時20-50%!讀者可以自行嘗試比較一下。是否省時還不是最重要的,更高的價值在於:使用專門驅動或自動驅動編碼調試,實際上也已經把令人望而生畏的單元測試工作完成了一半,並清除了實施單元測試的最主要障礙。

三、實現徹底單元測試

是什麼使單元測試難於實施?首先是代碼的可測性。可測性是什麼?如果一個類具有基本的可測性,那麼把它加入到另一個工程後(當然有關聯的文件也要加入)能夠通過編譯,這其實是很低的要求,但對於一個有一定規模的項目,如果開發調試時使用自然驅動,在完成編碼後才進行單元測試,那麼通常都不具有可測性,因為開發人員常常在無意之中使代碼之間產生了不當耦合,這些不當耦合累積起來,會使整個項目的代碼糾纏在一起,造成難於測試。

使單元測試難於實施的另一個方面是建立測試用例。在本例中,如果由不熟悉代碼的測試人員建立測試用例,那麼他很可能不知道如何生成CToken對象 指針的列表。

如果邊開發邊使用專門驅動(測試代碼放在另一個工程中)或自動驅動調試,那麼一旦出現影響可測性的不當耦合就會及時發現及時解決,保證了代碼的可測性,另一方面,由於至少建立了一個測試用例,測試人員建立其他用例時只要修改一下輸入輸出數據,從而大大降低建立測試用例的難度。總之,使用專門驅動或自動驅動調試,在不增加開發工作量的同時,已經為單元測試打一下了堅實的基礎。

范例項目V0.1處於這樣一個階段:剛剛完成代碼編寫,並未完成單元測試,現有的多數測試用例都是編碼時用於調試的。在此基礎上,單元測試由誰做,難度都不大。VU的典型應用是通過三個 階段來完成針對一個函數的徹底的測試:

1)基本功能測試:測試代碼的基本功能;

2)完成白盒覆蓋:在現有用例的基礎上,使用測試用例設計器為未覆蓋的語句、條件、分支、路徑設計測試用例,達到100%語句、條件、分支、路徑覆蓋;

3)執行自動邊界測試捕捉意料之外的錯誤。

以上三階段可以由不同人員在不同時間完成,團隊可以根據實際情況做出靈活安排,下面是一個典型的開發測試流程。

1)開發人員邊開發邊使用VU調試測試,完成基本功能測試。在VU的支持下開發調試,可以大幅提高開發效率,絕不會影響開發進度。也許讀者會認為,開發人員沒有時間去設計測試用例,其實這是一種誤解,開發人員寫代碼時肯定要想清楚代碼的功能並且要使用基本的輸入進行調試,這些就是基本的測試用例,實際上不需要多做什麼。開發人員提交代碼同時提交測試代碼和測試報告。如果項目已完成或部分完成編碼,也建議先由程序員首先對重要代碼進行基本的功能測試。

2)測試人員檢查基本測試用例是否符合設計,並在此基礎上完成白盒覆蓋和邊界測試。由於有了初步的測試,保證了代碼可測性,不可能產生因為不當耦合造成難於測試的狀況;在現有用例的基礎上,使用測試用例設計器找出遺漏用例也不會有太大障礙,這就使測試人員的工作易於進行。測試人員只需要提交更新過的測試代碼和測試報告,不需要另外記錄測出的問題。

3)開發人員下載新的測試代碼和測試報告,執行整體測試,然後針對報告了錯誤的函數執行函數測試以獲取詳細信息,必要時進行調試,找出錯誤,修改代碼,使所有測試通過,再次提交產品代碼和測試報告。

4)測試人員再次執行整體測試,驗證所有的測試均已通過。

以上流程是動態和反復的,並不是編碼完成後再單元測試。開發人員寫完一個類後即可提交代碼由測試人員完成白盒覆蓋和邊界測試。另外,團隊可以根據開發與測試人員的比例調整工作份額,如果團隊沒有測試人員,那麼由開發人員完成全部單元測試也是可行的。

徹底的單元測試對於軟件開發來說,其價值是難於估量的:除了保證局部代碼的質量外,有了單元測試,任何時候修改代碼後都可以通過回歸測試來自動檢查修改是否引入錯誤,這就使開發過程可以適應頻繁變化的需求,系統分析、概要設計和詳細設計都可以做得簡單一些,也更能適應螺旋式開發過程,以後的維護升級成本也會大幅降低,同時,高質量的代碼使集成測試和系統測試的工作量降低很多(實際上單元測試已包含了大部分的集成測試),發現問題後的修改也會高效得多。總之,要提高軟件開發質量、降低軟件開發成本,最有效的改進就是進行徹底的單元測試,如果不進行單元測試,任何流程改進都無法保證產品質量,因為,程序始終是由代碼構成的,代碼的質量沒有保證,軟件的質量拿什麼來保證?單元測試並不排斥其他過程改進,相反,單元測試對開發流程中的所有環節幾乎都有促進作用。

下邊再談談關於白盒覆蓋的話題。使用VU實施單元測試,100%的語句、條件、分支覆蓋通常都是很容易的,路徑覆蓋有時候會很難,例如,我們所舉的例了,CExFunction::ParseOneParameter (),有九十多條路徑,要覆蓋似乎不現實或沒必要,這種狀況通常是設計不合理造成的,例如,CExFunction::ParseOneParameter ()函數的代碼分為三塊:1、解析缺省值,2、解析數組,3、解析類型和參數名,前兩塊解析了缺省值和數組後把相應的Token從列表中刪除,這樣的話,第3塊與前兩塊是沒有邏輯關系的,但是,這3塊代碼會組合出很多路徑,沒有邏輯關系的代碼所組合出來的路徑是沒有意義的,這些代碼具有"高耦合低內聚"的特征,不應該放在一個函數中。范例中另外寫了一個函數:CExFunction::ParseOneParameter2(),把以上三塊代碼分別獨立出來自成一個函數,這樣 每個函數都能完成100%的路徑覆蓋,重構後的代碼既易於測試,也易於維護。范例中有大量類似的函數,甚至有超過200行的函數,這是為了檢驗VU的適應能力,以後的版本是會進行重構。我們建議程序員完成編碼後,檢查一下路徑數量,如果路徑很多,代碼很可能需要分拆,合理的路徑數量應該是等價類數量的一至兩倍。另外,從邏輯結構圖也可以看出來:圖中有兩個或兩個以上串聯的復雜分支結構,往往表示代碼的結構有問題。

VU的邏輯結構圖具有屏蔽對象的功能,因此,遇到上述情形時可以通過交替屏蔽部分分支結構的方式來實現路徑覆蓋,但這不是我們推薦的方式,因為它雖然可以保證測試的完整性,但並沒有改進代碼的結構。

關於單元測試和范例項目,還有很多值得敘述的話題,例如內存洩漏測試以及一些復雜問題的處理等等,這裡暫且不談。最後談談已完成編碼的項目的單元測試。對於已完成編碼的項目,最好先由開發人員"去耦合",方法是將代碼文件從底層向上排列,按順序依次將文件加入到另一個工程並編譯,如果產生編譯錯誤,則想辦法消除編譯錯誤 ,VU提供了文件排序工具,具體的使用方法請查閱幫助中《測試舊工程》部分。 完成“去耦合”後,由開發人員對自己編寫的代碼完成基本功能測試,測試人員完成白盒覆蓋和邊界測試。對於編碼過程中使用自然驅動調試的已完成編寫的代碼,完全由測試部門進行單元測試通常是很難的。

附:

C++代碼文檔生成器

本軟件的主要功能是解析C/C++代碼,依據代碼及注釋自動生成代碼文檔。點擊這裡浏覽本文檔生成器依據自身代碼生成的文檔,文檔格式為XML,需要XML解析器的支持,請允許ActiveX運行,如仍無法浏覽,請下載安裝微軟的XML插件。

這是凱樂軟件測試部主持的一個開源項目,模擬最糟糕的開發團隊,最混亂的開發流程,以惡劣環境下的實戰檢驗和展示Visual Unit在軟件開發和測試中的應用。此項目由很少寫代碼的測試和預研部門開發,人員不固定,時間也不固定,誰有空就寫上一些;沒有設計,沒有文檔,基至也不在代碼文件中保存編碼人員的信息,成員完全依賴於閱讀代碼和測試用例來理解其他成員寫的代碼;除了簡單的命名規則外,沒有其他規范,甚至連一個函數原則上不能超過50行之類的基本規范也沒有(范例中有超過200行的函數CMacro::Unwind(),一萬多條路徑)。總之,此項目所展示的編碼調試方式和單元測試方法,是任何開發團隊都可以實施的。詳細信息,請閱讀相關文檔:《高效開發與徹底測試》。

代碼文檔生成器使用說明

1) 不需要安裝,雙擊啟動;

2) 選擇要生成文檔的項目目錄,可以選擇多個目錄;

3) 在編譯條件輸入框中添加編譯條件(可選);

4) 選擇文檔的保存目錄;

5) 點擊"生成",即可生成XML文檔;

6) 將XSL目錄下的文件拷貝到文檔目錄,點擊index.htm即可浏覽文檔;

7) 通過修改XSL目錄下的文件可以定制顯示格式或裝飾頁面。

項目源代碼使用說明

源代碼包括產品工程和測試工程:

產品工程目錄:/源代碼/Docer/

測試工程目錄:/源代碼/TestDocer/

安裝Visual Unit1.3,啟動VC6,將產品工程目錄及Visual Unit安裝目錄/include/添加到搜索路徑,更詳細的信息請查看Visual Unit幫助《新建測試工程-VC6》。

產品工程可以使用VC6直接編譯。

測試工程的編譯運行:

1)啟動Visual Unit(個人版或企業版),導航窗口->菜單->目錄,選擇產品工程和測試工程的目錄;

2)試一下編譯測試工程,如果通不過編譯,請查看幫助《編譯錯誤》章節的說明;

3)在導航窗口選擇要測試的源文件,如產品工程目錄下的ExFunction.cpp文件;

4)在導航窗口函數列表中選擇一個函數,如ParseOneParameter,編譯並執行測試工程(Execute Program或Ctrl+F5),即可執行測試。

5)企業版用戶可以使用IDE插件,自動選擇要測試的文件和函數,請查看幫助中《使用IDE插件》章節。

6)要調試程序,添加斷點,如在CExFunction::ParseOneParameter()入口處加斷點,執行調試(Go或F5),即可進入調試,調試前可以打開測試用例編輯器選擇調試輸入(測試用例),調試過程中也可以切換用例,請參考幫助《排錯--調試》。企業版用戶,可以直接執行IDE插件的調試命令,無需手工斷點。

7)大多數代碼(比較簡單的除外)都是邊開發邊在Visual Unit的支持下調試的,不需要界面,隨便選擇一個函數都可以立即進入調試,也可以隨便增刪修改調試輸入(使用測試用例編輯器)。

8)目前版本僅實現了最基本功能,為了檢驗和展示VU的適應能力,很多代碼不完善或有重構的必要,同時也有很多測試用例不完整。如果您有意擴展 本項目的功能,請在Visual Unit的支持下編碼調試,即使是免費的個人版,也能大幅提高開發的效率和質量。

變量命名規則

m 成員變量

g 全局變量

s 靜態變量

p 指針

i 輸入參數

o 輸出參數

示例

CString name; //局部變量

CStrin mName; //成員變量

CString iName; //輸入參數

CString& oName; //輸出參數

CString gName; //全局變量

CString* pName; //局部變量,指針

CString* mpName; //成員變量,指針

CString* ipName; //輸入參數,指針

CString* opName; //輸出參數,指針

CString* iopName; //輸入輸出參數,指針

本文配套源碼

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved