功能測(cè)試或集成測(cè)試是關(guān)系到整體系統(tǒng)功能的測(cè)試,而不只是牽涉到小段代碼(單元)。這需要將已經(jīng)單獨(dú)測(cè)試好的模塊組裝起來(lái),以保證其連接時(shí)也能像預(yù)期一樣正常
工作。
JUnit是進(jìn)行Java程序測(cè)試最常用的測(cè)試框架。
大多數(shù)Java開(kāi)發(fā)人員都善于解決邏輯結(jié)構(gòu)測(cè)試問(wèn)題,比如如何建立測(cè)試預(yù)設(shè)環(huán)境、利用斷言?添加測(cè)試方法、用setup方法進(jìn)行初始化等。然而,如果Java開(kāi)發(fā)人員能更深入地了解如何設(shè)計(jì)功能測(cè)試集來(lái)有效地檢驗(yàn)代碼是否正常運(yùn)行,他們將獲得更多的益處。
這篇文章介紹了可以建立有效 JUnit功能測(cè)試集的策略。包括:
確定測(cè)試用例覆蓋所有程序行為。
確定代碼入口點(diǎn):測(cè)試程序整體功能的主要代碼段。
匹配入口點(diǎn)與相應(yīng)的測(cè)試用例。
根據(jù)初始化 /運(yùn)行/檢查流程創(chuàng)建測(cè)試用例。
設(shè)計(jì)并利用運(yùn)行時(shí)事件表進(jìn)行測(cè)試。
我將結(jié)合Saxon(一個(gè)可以處理XPath、XQuery和XSLT 的XML工具)的源代碼來(lái)具體闡述這些策略。Saxon由約50000行Java代碼組成,它是開(kāi)源的,代碼風(fēng)格優(yōu)良,注釋文檔詳盡。
確定用例
功能測(cè)試有兩個(gè)相輔的目標(biāo):覆蓋率與粒度。為確保完整性,功能測(cè)試必須覆蓋程序提供的所有功能,且必須在各組件水平上分別進(jìn)行測(cè)試。一個(gè)測(cè)試可以建立在另一個(gè)測(cè)試的基礎(chǔ)上,但任何測(cè)試都不能用來(lái)驗(yàn)證兩項(xiàng)功能。
建立一個(gè)全面的功能測(cè)試集,第一步是列出程序可以實(shí)現(xiàn)的所有行為。這可以通過(guò)使用特定的用例模擬外部因素(程序使用者或其它軟組件)執(zhí)行系統(tǒng)內(nèi)部的功能來(lái)實(shí)現(xiàn)。
一個(gè)典型的企業(yè)Java程序應(yīng)該包含各種用戶(hù)所需的詳細(xì)文檔,包括用例說(shuō)明、非功能性要求、測(cè)試用例說(shuō)明、用戶(hù)界面設(shè)計(jì)文檔、模型、用戶(hù)個(gè)人信息以及其它各種人工生成的信息。一般來(lái)說(shuō)簡(jiǎn)單的應(yīng)用程序只有一個(gè)簡(jiǎn)單的說(shuō)明文檔。
借助這些文檔,你可以快速確定需要測(cè)試的用例。每個(gè)測(cè)試用例都描述了應(yīng)用程序可以執(zhí)行的一項(xiàng)功能。用規(guī)模相近的測(cè)試方案確定唯一的功能是一個(gè)好習(xí)慣,而較大的方案可以根據(jù)其檢驗(yàn)的功能拆分為較小的方案。
有許多種建立用例模型的方法,其中最簡(jiǎn)單的便是輸入/輸出匹配法。在Saxon的query類(lèi)中,最簡(jiǎn)單的用例是傳送一個(gè)查詢(xún)文件、一個(gè)查詢(xún)請(qǐng)求和一個(gè)輸出文件路徑。輸出文件若不存在,將根據(jù)要求創(chuàng)建,并在文件中顯示查詢(xún)結(jié)果。
更復(fù)雜的用例可能需要輸入更多的信息或輸出更多的結(jié)果。然而,用例并不關(guān)心功能是如何在內(nèi)部實(shí)現(xiàn)的。對(duì)它們來(lái)說(shuō),軟件就像是一個(gè) “黑盒子”,只要運(yùn)行正常,即使真正實(shí)現(xiàn)軟件功能的是盒子里的侏儒也無(wú)所謂。這是很重要的一點(diǎn),因?yàn)檩斎?輸出匹配用例很容易直接轉(zhuǎn)換為測(cè)試用例,使得復(fù) 雜的說(shuō)明與簡(jiǎn)單的測(cè)試吻合,確定該運(yùn)行的功能正常運(yùn)行,而不該運(yùn)行的功能如預(yù)期一樣失效。
如果類(lèi)相對(duì)比較簡(jiǎn)單,或者已有列舉類(lèi)所有功能的說(shuō)明文檔,為指定入口點(diǎn)描述用例將很容易。如果不是這樣,或許就需要研究類(lèi)可能有的所有行為(確定類(lèi)的目的與用法)。如果你想知道所有調(diào)用代碼的地方,也可以從代碼中提取用例。
最可能的情況是,根據(jù)開(kāi)發(fā)人員提供的類(lèi)的一些基本說(shuō)明文檔,可以完全確定這些類(lèi)應(yīng)有和不應(yīng)有的行為。基于此,設(shè)計(jì)一套準(zhǔn)確的用例集。
轉(zhuǎn)換測(cè)試用例
每個(gè)測(cè)試用例都由兩部分組成:輸入和預(yù)期輸出。輸入部分包括所有創(chuàng)建變量或?yàn)樽兞抠x值的測(cè)試用例語(yǔ)句。預(yù)期輸出部分則表明應(yīng)該得到的輸出結(jié)果,它應(yīng)該顯示斷言成立或“沒(méi)有異常”(不存在斷言語(yǔ)句時(shí))這樣的信息。
基本的輸入/輸出模式是理解測(cè)試用例模型最簡(jiǎn)單易用的辦法。它采用一般函數(shù)(傳遞參數(shù),獲取返回值)和大多數(shù)用戶(hù)行為(按某個(gè)鍵實(shí)現(xiàn)某項(xiàng)功能)慣用的模式。然后,可以用該模式進(jìn)行:
初始化:建立測(cè)試預(yù)設(shè)環(huán)境。代碼初始化可以在測(cè)試開(kāi)始時(shí)進(jìn)行或通過(guò)調(diào)用setUp()方法實(shí)現(xiàn)。
運(yùn)行:調(diào)用被測(cè)試的代碼,記錄所有值得注意的輸出和數(shù)據(jù)。
檢查:使用斷言語(yǔ)句確保代碼正常運(yùn)行。
舉例來(lái)說(shuō),假設(shè)要測(cè)試Saxon庫(kù)的轉(zhuǎn)換類(lèi)入口點(diǎn)。其中一個(gè)用例是將XML文件轉(zhuǎn)換為HTML文件,當(dāng)然前提是已有描述這個(gè)轉(zhuǎn)換的XSL文件。輸入這三個(gè)文件的路徑,就應(yīng)該輸出HTML文件的內(nèi)容。這可以直接轉(zhuǎn)為下面的測(cè)試:
public void testXSLTransformation() { /* initialize the variables (or do this in setUp if used in many tests) */ String processMePath = "/path/to/file.xml"; String stylesheetPath = "/path/to/stylesheet.xsl"; String outputFilePath = "/path/to/output.xml"; //do the work Transform.main(new String[] { processMePath, stylesheetPath, "-o", outputFilePath } ); //check the work assertTrue(checkOutputFile(outputFilePath)); } |
每一步都可以根據(jù)需要進(jìn)行增減。這里聲明的變量也可以簡(jiǎn)單地通過(guò)調(diào)用方法來(lái)賦值。預(yù)期輸出的實(shí)現(xiàn)是由幾個(gè)步驟組成。如果成功得到預(yù)期輸出,有時(shí)可以省略檢查步驟。
雖然這個(gè)模式簡(jiǎn)單且靈活可變,但是第二步必不可少。這個(gè)模板沒(méi)有告訴我們尋找要測(cè)試代碼的方法,也不能保證代碼以方便測(cè)試的方式運(yùn)行。這是個(gè)需要認(rèn)真考慮的問(wèn)題。
功能測(cè)試
通過(guò)確定執(zhí)行程序功能的主要代碼段,可以將測(cè)試建立在一個(gè)更有效的環(huán)境下。由于這些類(lèi)提供了從系統(tǒng)外部進(jìn)行測(cè)試的途徑,所以也是代碼的入口點(diǎn)。
因此,功能測(cè)試的整體目標(biāo)就是確定一組可以訪問(wèn)系統(tǒng)功能的高層接口類(lèi)。這些類(lèi)的獨(dú)立性越高越好。畢竟,如果能將類(lèi)從環(huán)境中分離出來(lái),測(cè)試起來(lái)會(huì)更加容易。
確定作為入口點(diǎn)的代碼是一個(gè)簡(jiǎn)單的過(guò)程。在代碼庫(kù)中,通常有幾個(gè)控制該庫(kù)所有功能的入口點(diǎn)。這些外部類(lèi)作為客戶(hù)端代碼,與庫(kù)的中介對(duì)象將開(kāi)發(fā)人員從復(fù)雜的代碼分析中解脫出來(lái)。這些便是應(yīng)當(dāng)首先對(duì)其方法進(jìn)行測(cè)試的類(lèi)。
比如,Saxon有一小組類(lèi)作為邏輯入口點(diǎn)提供對(duì)庫(kù)的訪問(wèn)。通過(guò)對(duì)外部類(lèi)進(jìn)行編碼操作,比如轉(zhuǎn)換、設(shè)置和查詢(xún),客戶(hù)端代碼可以訪問(wèn)庫(kù)的許多功能 類(lèi),而無(wú)需考慮類(lèi)的接口問(wèn)題,甚至無(wú)需擔(dān)心這些類(lèi)是否存在。這些外部類(lèi)用高層易用的接口提供一個(gè)簡(jiǎn)單的方式對(duì)系統(tǒng)功能進(jìn)行測(cè)試,這正是一個(gè)優(yōu)良的庫(kù)的特 征。
程序代碼中的各個(gè)功能模塊通常是各自獨(dú)立的。在某些代碼中,甚至可以認(rèn)為這些模塊各自對(duì)應(yīng)不同的、可通過(guò)大量外部類(lèi)訪問(wèn)的庫(kù)。這些類(lèi)查找高層接口的邏輯位置。插件結(jié)構(gòu)通常都采用這種設(shè)計(jì)模式:每個(gè)插件程序都有一個(gè)可以有效執(zhí)行內(nèi)部代碼全部功能的簡(jiǎn)單接口。
在一些非嚴(yán)格描述的系統(tǒng)中,通常有一個(gè)所有程序行為的中介點(diǎn)。在MVC架構(gòu)中,這個(gè)中介類(lèi)一般作為“控制器”,負(fù)責(zé)配置系統(tǒng)各部分的請(qǐng)求路由。整體系統(tǒng)的功能主要由這個(gè)控制器連接的類(lèi)實(shí)現(xiàn),因此,這些類(lèi)是測(cè)試的主要對(duì)象。
比如在 Applet程序設(shè)計(jì)中,java.applet.Applet的派生類(lèi)就是所有代碼的中心處理單元。根據(jù)代碼的分解程度,測(cè)試焦點(diǎn)可以放在Applet 子類(lèi)或與其連接的類(lèi)上。
連接各個(gè)模塊的代碼也是測(cè)試的主要對(duì)象。將應(yīng)用程序請(qǐng)求轉(zhuǎn)換為數(shù)據(jù)庫(kù)查詢(xún)的類(lèi),以及有相似功能的適配類(lèi)是其次應(yīng)該考慮的測(cè)試對(duì)象。
各種基于MVC(模式-視圖-控制器)架構(gòu)的組件可以用其它的測(cè)試框架(比如Junit的擴(kuò)展)進(jìn)行測(cè)試。例如,Struts的 action類(lèi)就最好使用JUnit的擴(kuò)展StrutsTestCase進(jìn)行測(cè)試;服務(wù)器端的組件(如Servlets、JSP和EJB)最好用 Catus進(jìn)行測(cè)試;而HttpUnit則是對(duì)Web應(yīng)用程序進(jìn)行黑盒測(cè)試的最好框架。本文討論的所有技術(shù)都可應(yīng)用于這些框架環(huán)境下的測(cè)試。
從用例到測(cè)試用例
每個(gè)入口點(diǎn)都必須與相應(yīng)的用例匹配。某些情況下可以忽視這一步,因?yàn)轭?lèi)名的自記錄可以實(shí)現(xiàn)自動(dòng)匹配,比如 Saxon中的轉(zhuǎn)換類(lèi)可以實(shí)現(xiàn)XSL轉(zhuǎn)換,查詢(xún)類(lèi)可以進(jìn)行XQuery轉(zhuǎn)換。
其它情況則要復(fù)雜得多。通常用例描述的功能只能以橫切關(guān)注點(diǎn)的方式存在,不能用任何單獨(dú)的類(lèi)進(jìn)行例證。只有幾組類(lèi)交互時(shí)或滿(mǎn)足一定條件時(shí),才能觀察到功能行為。這種情況下,測(cè)試的初始化程序會(huì)比較長(zhǎng),或者可以用 setUp()方法提供需要的測(cè)試環(huán)境。
而調(diào)用代碼的運(yùn)行程序應(yīng)該盡可能地設(shè)計(jì)成一行,以減少與被測(cè)試代碼的關(guān)聯(lián),這可以有效避免對(duì)邊緣效應(yīng)與不穩(wěn)定實(shí)現(xiàn)細(xì)節(jié)的依賴(lài)。測(cè)試的檢查階段是 最復(fù)雜的,因?yàn)檫@個(gè)階段經(jīng)常需要添寫(xiě)非測(cè)試用代碼。測(cè)試時(shí)可能需要對(duì)結(jié)果進(jìn)行嚴(yán)格的分析以確保其符合要求。有時(shí)甚至需要將這個(gè)過(guò)程分為幾步來(lái)完成,以取得 測(cè)試可以識(shí)別的結(jié)果。在XSL轉(zhuǎn)換中,這兩種情況都是可能的,結(jié)果儲(chǔ)存在文件中,然后以XML格式讀入內(nèi)存并進(jìn)行準(zhǔn)確性分析。
Saxon中有個(gè)相對(duì)簡(jiǎn)單的例子。已有XML文件和XPath表達(dá)式的情況下,Saxon可以執(zhí)行表達(dá)式并返回匹配列表。Saxon中的XpathExample樣本類(lèi)就是用來(lái)執(zhí)行這種任務(wù)的。基于以上分析,可以設(shè)計(jì)如下的測(cè)試流程:
public void testXPathEvaluation() { //initialize XPathEvaluator xpe = new XPathEvaluator( new SAXSource(new InputSource("/path/to/file.xml"))); XPathExpression findLine = xpe.createExpression("/some/xpath[expression]"); //work List matches = findLine.evaluate(); //check assertTrue(matches.count() > 0); } |
兩次輸入的都是字符串常量,輸出的則是所匹配的列表,可以用來(lái)驗(yàn)證匹配結(jié)果的正確性。這些工作都由一行代碼完成,這行代碼只是簡(jiǎn)單地調(diào)用了被測(cè)試的方法。
另一種可能的情況是XPathEvaluator沒(méi)有調(diào)用createExpression()方法。因?yàn)楸磉_(dá)式不存在,這時(shí)可能會(huì)顯示錯(cuò)誤信息。
將輸入的源文件名和表達(dá)式保留在測(cè)試用例中不是個(gè)好習(xí)慣。某些項(xiàng)目(服務(wù)器名、用戶(hù)名和密碼等)不應(yīng)該出現(xiàn)在測(cè)試文件中,它們應(yīng)該可以根據(jù)情況 自由設(shè)置。并且,測(cè)試用例的設(shè)計(jì)應(yīng)該方便測(cè)試驅(qū)動(dòng)和測(cè)試數(shù)據(jù)的分離、測(cè)試驅(qū)動(dòng)對(duì)大范圍數(shù)據(jù)的可重用性和測(cè)試數(shù)據(jù)對(duì)測(cè)試驅(qū)動(dòng)的可重用性。另一方面,不要將一 個(gè)簡(jiǎn)單的測(cè)試用例實(shí)現(xiàn)設(shè)計(jì)地過(guò)于復(fù)雜。一般來(lái)說(shuō),測(cè)試用例已經(jīng)說(shuō)明了系統(tǒng)的大部分狀態(tài),并可對(duì)其進(jìn)行參數(shù)描述,所以無(wú)需在測(cè)試中進(jìn)行過(guò)于詳細(xì)的參數(shù)描述。
許多代碼段可能出現(xiàn)在不止一個(gè)測(cè)試用例中。有經(jīng)驗(yàn)的面向?qū)ο箝_(kāi)發(fā)人員會(huì)嘗試對(duì)其進(jìn)行重構(gòu)并創(chuàng)建通用類(lèi)和有效方法。有時(shí)候這樣做非常有用,比如登錄過(guò)程應(yīng)該設(shè)計(jì)成所有測(cè)試用例可用的方法。 但是,不要過(guò)度設(shè)計(jì)測(cè)試,這些Java類(lèi)僅僅是用來(lái)驗(yàn)證應(yīng)用程序的功能行為而已。
測(cè)試用例是脆弱的。比如,如果開(kāi)發(fā)人員更改了testXPathEvaluation測(cè)試中輸入文件的位置,或者creatExpression方法簽名有所變動(dòng),測(cè)試腳本就會(huì)失效。
對(duì)于應(yīng)用程序的測(cè)試用例實(shí)現(xiàn)來(lái)說(shuō),大量的重復(fù)性工作與改動(dòng)是不可避免的。因此,可跟蹤性對(duì)于所有的測(cè)試用例都是至關(guān)緊要的。出現(xiàn)問(wèn)題的時(shí)候,如果能為開(kāi)發(fā)人員指出相應(yīng)的測(cè)試用例說(shuō)明和用例說(shuō)明將有利于提高修正bug的速度。
因此,測(cè)試用例注釋中應(yīng)標(biāo)明原始說(shuō)明文檔的引用位置。這可以是一個(gè)簡(jiǎn)單的代碼注釋?zhuān)部梢詫?duì)每條測(cè)試都注釋相關(guān)用例和所測(cè)功能,這樣當(dāng)測(cè)試出現(xiàn)問(wèn)題時(shí)開(kāi)發(fā)人員就會(huì)收到一條相關(guān)信息。因此,在代碼中加入?yún)⒖疾⒕S護(hù)可追蹤性是很重要的。
設(shè)計(jì)運(yùn)行時(shí)事件表
要了解測(cè)試覆蓋的范圍,必須先了解所測(cè)試代碼如何運(yùn)行,以及各種靜態(tài)類(lèi)如何形成描述程序狀態(tài)的動(dòng)態(tài)對(duì)象圖表。
有許多模擬這種行為的方法,包括Granovetter圖和物件互動(dòng)圖。其基本思想是用圖形化的方式研究代碼以了解測(cè)試中涉及到的運(yùn)行時(shí)部分。 這些技術(shù)都可用運(yùn)行時(shí)事件表(Runtime Event Diagrams)來(lái)描述,因?yàn)檫@些圖表顯示了程序運(yùn)行時(shí)發(fā)生的事件,而非理論上類(lèi)可以控制的事件。這些圖表非常重要的原因包括:
首先,這些圖表便于從高層上理解代碼,并提供有用的說(shuō)明文檔。這個(gè)文檔與代碼的內(nèi)聯(lián)文檔不同。這些圖表顯示代碼的運(yùn)行時(shí)表現(xiàn),是產(chǎn)生代碼功能的地方,也易于對(duì)系統(tǒng)的了解;大多數(shù)設(shè)計(jì)模式和架構(gòu)在用對(duì)象和參考表示時(shí)要比用類(lèi)和域表示容易得多。
另外,這些圖表將測(cè)試執(zhí)行的代碼分類(lèi)列表,并確定測(cè)試是否會(huì)受到將來(lái)對(duì)任意代碼改動(dòng)的影響。如果開(kāi)發(fā)人員確定測(cè)試A是建立在B、C和D的基礎(chǔ)上,她就可以確定如果對(duì)B、C或D做出改動(dòng)就需要對(duì)A進(jìn)行重新測(cè)試(確保向后兼容)。
以盡可能少的步驟模擬系統(tǒng)是個(gè)好方法。總的來(lái)說(shuō),實(shí)際調(diào)用與此無(wú)關(guān),重要的是系統(tǒng)如何作為整體運(yùn)作以獲得預(yù)期目標(biāo)。可以用簡(jiǎn)化的模擬系統(tǒng)實(shí)現(xiàn)這個(gè)目的,該系統(tǒng)只關(guān)心對(duì)象間的基本交互,并用自然語(yǔ)言描述交互中發(fā)生的事件。
做出運(yùn)行時(shí)事件表后,就可以將其整合到類(lèi)文檔中。需要注意的是,為表添加一些限制可使其對(duì)類(lèi)的修改更有彈性。首先,一般不能使用方法名,因?yàn)樗?們會(huì)隨時(shí)間發(fā)生變化。取而代之的是更易理解的自然語(yǔ)言描述。其次,這些圖表主要是關(guān)于系統(tǒng)中各部分的交互。這是高層架構(gòu)上的設(shè)計(jì)方案,一般不會(huì)再做改動(dòng)。 最后,圖表是建立在類(lèi)型而非特定類(lèi)的基礎(chǔ)上。只要基本類(lèi)型不變,為維持交互協(xié)議的正常運(yùn)行,這些圖表就不需要更新。
一旦圖表創(chuàng)建成功,可以在許多方面獲得應(yīng)用。比如,一個(gè)圖表可以用來(lái)獲取系統(tǒng)如何運(yùn)作,以及如何運(yùn)用其交互部件實(shí)現(xiàn)功能的概覽。在某種程度上這是一種簡(jiǎn)化了的UML語(yǔ)言,它只描述關(guān)系到整體功能的系統(tǒng)部件:實(shí)例及其類(lèi)型、其它引用的實(shí)例,以及組件可以實(shí)現(xiàn)的功能。
這些圖表也可以用來(lái)分析系統(tǒng)的復(fù)雜性以及如何進(jìn)行簡(jiǎn)化。要確定簡(jiǎn)化系統(tǒng)的方法,可以查找系統(tǒng)中使用過(guò)一到兩次的對(duì)象,并為其尋找其它可能更合適的位置。也可以查找重復(fù)的任務(wù),將其封裝到方法或類(lèi)中。
然而,最重要的是圖表在測(cè)試中的應(yīng)用。通過(guò)對(duì)系統(tǒng)狀態(tài)的總結(jié),圖表可以幫助解決系統(tǒng)中出現(xiàn)的問(wèn)題。出現(xiàn)問(wèn)題時(shí),圖表中的信息便可用作參考。因?yàn)?只需要將系統(tǒng)目前狀態(tài)與預(yù)期狀態(tài)作比較即可,這樣確定問(wèn)題產(chǎn)生的原因也就變得比較簡(jiǎn)單了。對(duì)小組件的改動(dòng)不應(yīng)該影響整體架構(gòu),因此可以通過(guò)對(duì)照運(yùn)行時(shí)事件 表以保證系統(tǒng)仍然正常運(yùn)行。并且,當(dāng)有重要組件發(fā)生變動(dòng)時(shí),可以用運(yùn)行時(shí)事件表對(duì)照系統(tǒng)當(dāng)前狀態(tài)以獲取系統(tǒng)修正方案。由于將系統(tǒng)作為整體和對(duì)預(yù)期功能的描 述,運(yùn)行時(shí)事件表也可以看作是一種結(jié)構(gòu)化的單元測(cè)試。如果系統(tǒng)有變動(dòng),可以更容易地做出修正以維持系統(tǒng)的正常功能。
如果經(jīng)常因細(xì)節(jié)問(wèn)題影響對(duì)全局的把握,就應(yīng)該使用圖表。其高層本質(zhì)可以用來(lái)分析軟件的設(shè)計(jì)模式,就像反模式一樣。還有許多其它用途,并且當(dāng)運(yùn)行時(shí)事件表、測(cè)試用例說(shuō)明和用例說(shuō)明沒(méi)有描述所需的細(xì)節(jié)時(shí),它還提供了直接進(jìn)行代碼分析的路線圖。
利用功能測(cè)試進(jìn)行回歸測(cè)試
最后,為回報(bào)你在功能測(cè)試上做出的努力,配置一個(gè)與自動(dòng)生成的程序相應(yīng)的自動(dòng)化測(cè)試程序。這個(gè)程序不只從功能上測(cè)試代碼,還可以同時(shí)進(jìn)行常規(guī)的 回歸測(cè)試。現(xiàn)在大多開(kāi)發(fā)項(xiàng)目都建立在龐大的代碼庫(kù)基礎(chǔ)上,如果不能對(duì)代碼庫(kù)進(jìn)行充分測(cè)試,開(kāi)發(fā)團(tuán)隊(duì)將無(wú)從決定對(duì)程序的修正是否會(huì)破壞現(xiàn)有的功能,結(jié)果就是 很難對(duì)這種代碼進(jìn)行擴(kuò)展或優(yōu)化。與此相反,如果開(kāi)發(fā)人員可以在全面的功能測(cè)試基礎(chǔ)上進(jìn)行回歸測(cè)試,優(yōu)化或擴(kuò)展代碼時(shí)就不必?fù)?dān)心可能會(huì)引發(fā)不可預(yù)料的問(wèn)題。 畢竟,沒(méi)有比做完回歸測(cè)試后發(fā)現(xiàn)一切正常更令人心情愉快的事了。