測試驅(qū)動的設計與開發(fā)_第1頁
測試驅(qū)動的設計與開發(fā)_第2頁
測試驅(qū)動的設計與開發(fā)_第3頁
測試驅(qū)動的設計與開發(fā)_第4頁
測試驅(qū)動的設計與開發(fā)_第5頁
已閱讀5頁,還剩29頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

測試驅(qū)動的設計與開發(fā)你的代碼工作嗎?“這段代碼很簡單,不可能出錯”“我試過了,它是正常工作的呀”“我用Debugger測試過了,我遍歷了所有程序分支,內(nèi)存中的值都是對的”最好的方法是寫一段另外的代碼來證明它,讓電腦來告訴我們它是工作的。什么是單元測試(UnitTest)單元測試是一段能夠放在批處理中自動運行的,用來測試Classes的程序。單元測試測試一小段代碼或一個足夠小的功能。單元測試程序調(diào)用這小段代碼或功能,并驗證返回的結(jié)果是否符合預先設定的結(jié)果。每個單元測試至少應該有兩個測試例子(TestCase):NegativePositive單元測試是軟件工程的一個關(guān)鍵部分。什么是AcceptanceTestAcceptanceTestareprogramsorscriptsconfiguredtotestthatpackages(groupsofclustersofclasses)meetexternalrequirementsandachievegoals,suchasperformance.Theyincludescreen-drivingprogramsthattestGUIsfromwithout.AcceptanceTest是對軟件做End-To-End的測試,衡量軟件是否符合用戶需求的指標,也就是驗收測試。什么是RegressionTest“Regressiontestingistheprocessofvalidatingmodifiedpartsofthesoftwareandensuringthatnonewerrorsareintroducedintopreviouslytestedcode.”一句話,RegresstionTest就是要重新測試所有的代碼和功能。RegressionTest和DevelopmentTest的不同在于RegressionTest需要重用已經(jīng)建立的所有的測試單元(UnitTest)和功能測試套件(FunctionalTest)。RegressionTest的基礎是完整的自動單元測試和功能測試。什么是NightlyTestNightlyTest就是每晚自動運行所有的UnitTest和AcceptanceTest。NightlyTest是XP中的ContinuousTest的一個練習(Practice)。NightlyTest可以準確的反映項目開發(fā)的進度和質(zhì)量。NightlyTestNightlyTest是軟件開發(fā)中一個保證開發(fā)之質(zhì)量的最有效的方法,也是衡量軟件之質(zhì)量和開發(fā)效率的最好的指標。NightlyTest就是每天工作結(jié)束,所有的代碼都Checkin到SourceControl后,自動運行所有的UnitTest和FunctionTest。測試的結(jié)果應該自動分發(fā)給開發(fā)人員和管理層。兩個指標數(shù)值:測試例子的通過率–單元測試必須是100%通過。FunctionalTest應該按計劃的通過。單元測試的覆蓋率–表明有多少Class被測試過和測試的完善程度。測試優(yōu)先的編程在寫任何代碼之前,先寫它的UnitTest。“Neverwritealineoffunctionalcodewithoutabrokentestcase”KentBeckTest-FirstProgramming是一種測試技術(shù)嗎?Test-FirstProgramming首先是一種分析方法。它迫使程序員仔細思考要做什么和不要做什么(而不是如何具體的實現(xiàn))。特別是各種例外的情況,并用程序語言正式的寫下來。這就好像在程序員的任務和程序員之間簽訂了一個清晰的正式合同。Test-FirstProgramming是一種設計方法。UnitTest測試的事程序,而不是一個想法。程序員必須清晰的定義程序的界面才能寫出它的UnitTest。而這時程序員是不知道(也不需要知道)里面的具體邏輯是如何實現(xiàn)的。程序員只需要考慮Class的界面和功能(Responsibility)。啊,你在做OO設計了。Test-FirstProgramming是一種質(zhì)量控制方法(QualityControl)。如何控制質(zhì)量呢?如何知道我的程序是否運行呢?我會不會漏了什么?運行一下UnitTest。Test-FirstProgramming是一種重構(gòu)和優(yōu)化的方法。我們總希望自己的代碼可以漂亮,運行的效率高,所以我們會不斷地去改進??墒侨绾伪WC改進和優(yōu)化后的質(zhì)量呢?會不會越改越糟?答案還是UnitTest。Test-FirstProgramming不是通常意義上的測試技術(shù),它的目的也不是僅僅用來測試你的代碼。Test-FirstProgramming是一種面向?qū)ο蟮拈_發(fā)方法。什么是Test-DrivenDesign(TDD)Test-DrivenDesign是一種開發(fā)風格,它要求程序員做到:在寫產(chǎn)品代碼之前,先寫它的單元測試(UnitTests)沒有單元測試的Class不允許作為產(chǎn)品代碼單元測試例子決定了如何寫產(chǎn)品代碼不斷地成功運行所有的單元測試例子不斷的完善單元測試例子Test-DrivenDesign是把需求分析,設計,質(zhì)量控制量化的過程!為什么會出現(xiàn)TDD現(xiàn)實中的設計(Design)和測試(Testing):面對一個新的開發(fā)任務,往往第一個念頭就是如何去實現(xiàn)它呢?“好像是這樣做的”感覺上差不多了。抓起任務就開始編碼,一邊寫,一邊修改和設計。哎,時間很緊。我先把任務實現(xiàn)了,然后再好好測試。還是不工作,時間不多了。做個快速但丑陋的修改吧。等有空來再來重新整理這些代碼吧。用Debugger運行幾次代碼,走完所有的我認為可能的分支。我感覺這些代碼應該行了。提交吧。哎,我也知道該寫一些自動的單元測試來把剛才在Debugger中的測試走一遍??墒悄鞘呛芏嗟幕畎?。這種情況要作自動測試太復雜了。還是手工作一下測試好了。為什么會出現(xiàn)TDD(Continue)程序員心中的測試:很郁悶的工作。對啊,程序員該做些新的,有創(chuàng)意的東西嘛。寫一些新的功能會更有趣些。我知道這些代碼會工作的。我的經(jīng)驗和感覺都這樣告訴我。只要沒人亂改我的代碼,應該就沒問題。再說這些邊緣情況幾乎不可能出現(xiàn)了。測試是QA的工作。自動測試太花時間(我要趕Deadline),不值得。如何面對這些現(xiàn)實和想法Test-DrivenDesignandDevelopment真的能行?試一試!如何做TestDrivenDesignandDevelopment

(Continue)然后為這個功能(Method)寫單元測試例子(UnitTest) 單元測試例子要覆蓋這個Method的“做什么”。 所以我們至少有了兩個測試例子:

TestCase1:測試成功增加一個用戶

TestCase2:測試增加一個已存在的用戶 其他邊緣情況測試:

TestCase3:傳入的Account對象為NULL如何做TestDrivenDesignandDevelopment

(Continue)寫Production代碼 我們清楚知道這段代碼需要做什么。因為我們有另一段代碼擺在那里,清晰的表明這段代碼的Contracts。

不用多,也不能少,只需要能實現(xiàn)再UnitTest中的Contracts和能夠通過它的UnitTest。

如何做TestDrivenDesignandDevelopment

(Continue)運行UnitTest

如果順利通過,你已經(jīng)很好的完成了你的任務。 如果沒通過,修補代碼直到能通過UnitTest為止。 如果出現(xiàn)在UnitTest中沒預先設定的結(jié)果,在UnitTest中增加一個TestCase,修補代碼直到通過所有的TestCase為止。TDD和PSPPersonalSoftwareProcess的DevelopmentDesignCodeBuildTestTest-DrivenDesignandDevelopmentAnalysisCodeUnitTestCodeBuildRunTestAnalysisDesignXP采用了TDDTDD是ExtremeProgramming中必須遵行的一個方法。TDD是XP中PairProgramming的工作模式。XP中把測試驅(qū)動的設計和開發(fā)做到極致。TDD的整個流程由兩個程序員一起執(zhí)行。XP正是因為采用了TDD才能夠做到每天的代碼都是ProductionCode和每個小的Release都能提供具備Production質(zhì)量的代碼并投入使用。有了TDD,XP才能降低風險,去擁抱變化。有了TDD,XP才能在計劃的時間內(nèi)完成計劃質(zhì)量的代碼。有了TDD,XP才能減少Code<->Fix環(huán)節(jié),從而減少項目成本。有了TDD,XPTeam才能對自己的工作充滿自信。TDD防止Over-Engineering在開發(fā)中采用TDD,可以有效的避免過度設計和開發(fā)。如果程序員不愿為一個Method寫測試例子或者認為現(xiàn)在沒有必要測試改Method,那這個Method多半是現(xiàn)在不需要的。TDD,程序員和管理層對程序員來說,通過運行UnitTest和FunctionalTest,每天下班的時候都可以清楚的知道自己的代碼是work的。對管理層來說,通過NightlyTest的結(jié)果,每天一早都清楚的知道項目的質(zhì)量和開發(fā)進度。XP中誰來寫TestsDeveloper:UnitTestAcceptanceTest(FunctionalTest)Customer:AcceptanceTestCustomer為每一個UserStory寫FunctionalTest。但通常用戶并不具備設計和開發(fā)FunctionalTest的能力,需要程序員的幫助。什么時候?qū)慣ests?如果你要寫一個新的功能,請先寫她的測試例子如果你要在沒有經(jīng)過測試的代碼上寫新的功能,請先寫目前代碼的測試例子如果你要Fix一個Bug,請先為這個Bug寫一個測試例子如果你要Refactor沒有測試過的代碼,請先寫一個測試例子如果你發(fā)現(xiàn)一個邊緣例外值,請為她寫一個測試例子Junit(Asle)Junit是由kentBeck和ErichGamma編寫的一個opensource的測試框架,用來編寫可重復的測試例子。測試論壇中的增加用戶methodpublicclassAccountDAOmySqlimplementsAccountDAO{ /** *Addauseraccount * *@paramAccount-Aaccountobjectthatcontainstheuserinfo,likeuserName, *password,email */ publicvoidaddAccount(finalAccountaccount)throwsSQLException, AccountAlreadyExistException{ …… }Junit(Asle)1.為對應的JavaClass建立一個TestCase。UnitTestCase應該放在和BusinessClass相同的Package中,但在不同的的物理位置。importjunit.framework.TestCase;importjunit.framework.TestSuite;importjunit.framework.Test;publicclassAccountDAOmySqlTestextendsTestCase{ publicAccountDAOmySqlTest(Stringname){ super(name); } }Junit(Asle)2.OverridesetUp()andtearDown() 如果需要,可以在setUp()中初始化需要的全局變量,資源等(比如DatabaseConnection,FileI/O或MockObjects等) 相應的,可以在tearDown()中釋放資源(DatabaseConnection,FileI/O和MockObjects等)publicclassAccountDAOmySqlTestextendsTestCase{

…… privateMysqlFixturemysqlFixtureIns=newMysqlFixture(); publicvoidsetUp()throwsException{ mysqlFixtureIns.setUp(); } publicvoidtearDown()throwsException{ mysqlFixtureIns.tearDown(); }

}Junit(Asle)3.為被測試的Method寫TestCase……publicvoidtestAddAccountNormal(){ AccountDAOmySqldao=newAccountDAOmySql(); Accountaccount=newAccount(USER_NAME,"charles","charles_hhb@hotmail"); try{dao.addAccount(account);Accountaccount_new=dao.findByUserName(account.getUserName());assertEquals("Expectingcharles",account.getUserName(),account_new.getUserName());assertEquals("Expectingcharles",account.getPassword(),account_new.getPassword());assertEquals("Expectingcharles@hotmail",account.getEmail(),account_new.getEmail());dao.removeAccount(account.getUserName());}catch(finalExceptione){e.printStackTrace();fail("Unexpectedexception::"+e.toString());}}Junit(Asle)publicvoidtestAddAccountAlreadyExist(){ AccountDAOmySqldao=null; Accountaccount=null; try{ //AddanAccount ……

dao.addAccount(account); fail("AccountAlreadyExistExceptionexpected"); }catch(finalSQLExceptione){ e.printStackTrace(); fail("Unexpectedexception::"+e.toString()); }catch(finalAccountNotFoundExceptionnotFound){ notFound.printStackTrace(); fail("Unexpectedexception:"+notFound.toString()); }catch(finalAccountAlreadyExistExceptionex){ //Pass try{ dao.removeAccount(account.getUserName()); }catch(finalSQLExceptionsql){ sql.printStackTrace(); fail("Unexpectedexception"); } }}Junit(ASle)運行這個UnitTest。Junit提供兩種運行界面:Swing(junit.swingui.TestRunner)JunitTestSuiteTestSuite用來運行所有的UnitTestsTestSuite的數(shù)型結(jié)構(gòu): | | | |每個PackageLevel都由一個AllTestTestSuite在每個TestSuite中,加入在本packagelevel中的所有單元測試例子(UnitTestCases)加入子Packagelevel中的所有AllTestSuite

JunitTestSuitepackageorg.redsoft.forum.dao;publicclassAllTests{ publicstaticvoidmain(Stringargs[]){ junit.textui.TestRunner.run(suite()); } publicstaticTestsuite(){ TestSuitesuite=newTestSuite();

//加入子package中的AllTestsuite suite.addTest(org.redsoft.forum.dao.mysql.AllTests.suite()); //加入本packagelevel中的UnitTestcase suite.addTestSuite(MysqlDataSourceTest.class); returnsuite; }}//EOCJFCUnit一個Junit的Extension,用來測試Swing-based的Application。一個最簡單的Sle:測試一個LoginScreenJFCUnit代碼片斷:設置測試環(huán)境privateLoginScreenloginScreen=null; privateTestHelperhelper=null; publicLoginScreenTest(Stringname) {super(name);} protectedvoidsetUp()throwsException { super.setUp(); helper=newJFCTestHelper(); loginScreen=newLoginScreen("LoginScreenTest:"+getName()); loginScreen.setVisible(true); } protectedvoidtearDown()throwsException{ loginScreen=null;helper.cleanUp(this);super.tearDown(); }代碼片斷:測試圖形界面JDialogdialog;JButtonexitButton=(JButton)helper.findNamedComponent("ExitButton", loginScreen,0);assertNotNull("CouldnotfindtheExitbutton",exitButton);JButtonenterButton=(JButton)helper.findNamedComponent("EnterButton", loginScreen,0);assertNotNull("CouldnotfindtheEnterbutton",enterButton);JTextFielduserNameField=(JTextField)helper.findNamedComponent("LoginNameTextField", loginScreen,0);assertNotNull("CouldnotfindtheuserNameField",userNameField);assertEquals("Usernamefieldisempty","",userNameField.getText());JTextFieldpasswordFie

溫馨提示

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

評論

0/150

提交評論