《敏 捷 教 練:如何打造優(yōu)秀的敏捷團隊》—10 測試驅動開發(fā)
第10章
測試驅動開發(fā)
我們碰到過很多團隊,他們都說自己是敏捷團隊,但依然嚴重依賴于手工測試。開發(fā)人員把軟件扔過墻頭給測試人員找問題;測試人員再把它連同大量缺陷報告踢回去。時間就這樣消耗在開發(fā)人員和測試人員的你來我往之中,拼命給軟件打補丁,好得差不多了再交付。
鼓勵團隊轉而嘗試測試驅動開發(fā)(Test-Driven Development,TDD)以減輕這種壓力。團隊可以使用自動化的測試來檢查代碼是否可以工作,只需等待數(shù)分鐘,而非數(shù)小時甚至數(shù)天。如此一來,有了堅實的基礎,開發(fā)人員就能更自信地開發(fā),測試人員也能專注于邊界案例,而不必為無關緊要的問題浪費時間。
進入這個自動化測試的涅槃,是你作為敏捷教練將要面臨的最大調(diào)整。這是一個很復雜的轉變,因為引入TDD需要應對技術、個人發(fā)展和團隊協(xié)作方面的挑戰(zhàn)。讓我們一起來了解TDD實現(xiàn)之路該如何起步,如何克服障礙。然后我們再來看該如何幫助團隊轉向持續(xù)集成。
10.1 ?引入測試驅動開發(fā)
要允許團隊花大量時間完成向TDD的遷移。他們很可能會花上好幾個月才能做到真正用測試來驅動他們的編碼。要想實現(xiàn)TDD,第一個挑戰(zhàn)就是找到切入點。我們推薦一次只選擇一個問題,而不是試圖搞一刀切的大動作。
如果團隊剛剛從零開始一個項目,就可以直接全面施行TDD(如前面補充材料所描述的那樣)。然而,大多數(shù)團隊都是在尚未有自動化測試的現(xiàn)有代碼的基礎之上進行開發(fā)的,他們面臨的第一個挑戰(zhàn)是如何給遺留代碼寫自動化測試。不必急于用測試來驅動代碼,讓團隊先從每天寫一些自動化測試開始,以緩解團隊步入TDD的壓力。這樣一來,在試圖以測試優(yōu)先方式工作前,他們才有時間可以提升技能并搭建測試基礎設施。
花時間和團隊一起工作,要理解代碼的真實狀態(tài)、團隊成員的能力水平以及每一個人到底有多大興致想要改變自己的工作方式。這時可以使用PrOpER循環(huán)(參見1.4節(jié))來消除采納TDD所要面對的一切障礙。
下面的故事詮釋了可能遭遇的一些典型挑戰(zhàn)。
引入TDD的腳步太快
Rachel
若干年前,我有一個合作團隊的情況好像很適合嘗試TDD。他們當時在用Java開發(fā)一個內(nèi)容管理系統(tǒng)。他們的開發(fā)經(jīng)理已經(jīng)安排好讓團隊開發(fā)人員去參加培訓課,磨煉JUnit編程技能。他讓我繼續(xù)跟進輔導團隊使用TDD。這個請求看起來十分清楚明白,但我并沒有意識到自己接下來會面對什么狀況。
表面上看來,這只是一個技術型的挑戰(zhàn)而已,團隊在他們的代碼中嵌入了對一些第三方文檔管理系統(tǒng)的調(diào)用。他們需要想方設法做到一點:無須調(diào)用這個庫也能寫測試。在我看來這不難做到。我很有信心他們可以使用測試替身(Test Double) [1]來消除對庫的調(diào)用。然而,在把TDD引入團隊的時候,需要解決的可不只是技術方面的挑戰(zhàn),還有和人相關的挑戰(zhàn)。
我開始安排自己和隊內(nèi)每個開發(fā)人員都結對編程一次。我的計劃是,嘗試給團隊正在開發(fā)的用戶故事編寫JUnit測試,由此入手。然而,剛開始第一天我就碰到了一大堆難題,昭示著這個團隊尚未準備好接受TDD。
那一天,剛開始還挺好,我和技術主管Dom坐一塊結對。他看起來挺忙的,不過還是很愿意嘗試寫一些自動化測試。他剛剛好才修復完一個缺陷,于是我們決定寫一個測試來驗證他所完成的修復。他敲擊命令行運行新寫的測試,很驚訝地看著測試運行失敗,很顯然他尚未完全修復那個缺陷!我們在單元測試中選擇的測試數(shù)據(jù)觸發(fā)了一個問題,而早些時候他手動測試代碼時就沒有考慮到。看起來經(jīng)歷這件事之后,他已經(jīng)確信給每個缺陷修復都寫自動化測試是個好主意!
我接著又和Dave結對,他正在寫解析XML格式輸入文件的代碼,相當簡單。他已經(jīng)寫好了一些單元測試可以在Eclipse里運行,我們又多增加了幾個簡單的測試用例。我介紹了一個XML斷言庫給他,或許能派上用場,除此之外,他看起來并不需要幫助。
隨后的一次結對很是艱巨。John才剛剛接觸Java,而且他也還沒有領會到太多面向對象編程的基本原則。他也不知道如何使用IDE編寫和運行測試。他使用了單一主測試方法,每次想要檢查代碼時都得修改這個方法才行。他在理解現(xiàn)有系統(tǒng)工作方式時顯得很吃力,但當我建議他去問問其他隊員時,他卻退縮了。我們花了將近一個小時的時間,才把他那個長測試方法給拆開,提取出一些JUnit測試,但這活兒真的沒啥收獲。
末了我又和Chris結對,他是團隊里唯一的合同工,使用的是另一個IDE——NetBeans。他看起來挺有經(jīng)驗的,但他擔心著給那些直接調(diào)用第三方庫的代碼寫單元測試會很困難。我提出來可以使用模擬對象(Mock Object[2]),他告訴我說有一名開發(fā)人員剛剛離開團隊,她曾在測試里使用過模擬對象。我們打開她寫的那些測試,看起來很不錯。可等我們想要運行的時候,就不是那么一回事了。她寫出測試后代碼也一直在變,甚至無法順利進行編譯!自從她離開后,團隊根本沒人運行過那些測試。早知如此,還不如她當初干脆別寫呢!
問題就出在這里。所謂“團隊”,工作起來并不是真的團隊。他們各自忙于不同區(qū)域的代碼,對如何寫測試的觀點也各不相同。沒有人運行別人寫的測試,甚至每個人用的IDE都不一樣。沒有人真心認同,更沒人想搞清楚采納TDD對團隊有何根本意義。
在開始做TDD之前,他們需要先做一些基本的鋪墊工作。團隊需要共同合作確立測試策略,把測試組織起來做成團隊任何人都可以運行的一個共享測試集。
后來,我發(fā)現(xiàn)了開發(fā)經(jīng)理要團隊采納TDD的動機,因為項目中測試人員的工作量已經(jīng)超負荷了。他們發(fā)現(xiàn)很多代碼相關的細碎問題,而這些問題本可避免,只要開發(fā)人員能夠針對自己的代碼做一些簡單的測試。但這個經(jīng)理沒有告訴團隊這個情況。他們需要知道這一點,才能理解為什么要接受TDD培訓和輔導,才有理由進行改變。
團隊的認同
正如前面故事所講,只教團隊如何寫測試并不夠。團隊還需要能一致承諾寫測試和運行測試。他們需要看到令人信服的理由,才會承諾花額外的時間去寫自動化測試。確保他們已經(jīng)理解TDD的好處并已領會驅動改變的幕后緣由。
讓團隊聚在一起,商定他們可以做出的承諾。找出阻止他們開始嘗試TDD的障礙,列個清單。接著再問他們有什么辦法可以移除這些障礙。使用同意梯級(參見2.4節(jié))幫助團隊決定應該先把精力花在哪些行動上。
該學學怎么寫測試
一旦他們被說服決定轉向TDD,隊員就需要學習如何操作。想要推他們一把的話,就找?guī)讉€有自動化測試和TDD經(jīng)驗的人去幫助他們。
指點他們,要想有一個良好的開端,可以參加商業(yè)培訓課程。不過,如果沒有培訓預算(或是沒有他們所使用編程語言的培訓課程),團隊就需要自學如何寫自動化測試。幫他們發(fā)起一個定期的編碼道場以提高測試編寫技能(參見本頁的補充內(nèi)容)。
團隊開始抓緊編寫自動化測試之后,要做好準備,團隊會變慢。提醒他們,在做計劃時要預留些時間學習如何編寫自動化測試。團隊還應該提前告知客戶,由于正在經(jīng)歷學習期,團隊速率很有可能會下降。
決定從何處入手寫測試
團隊不可能一下子就完成所有遺留代碼測試的改造。他們需要以迭代方式做這件事。幫助他們找到切入點。
把團隊聚在一起商定測試策略,以決定如何測試不同區(qū)域的代碼。在白板上畫一張軟件架構的草圖(如圖10.1所示)。和團隊一起走查這個架構,找出其中最能夠受益于自動化測試的部分。給白板拍照,把討論內(nèi)容留存下來,回頭等團隊想要繼續(xù)增加測試的時候,再拿出來看。
補充內(nèi)容中定義描述的單元測試是一個不錯的切入點。隔離待開發(fā)代碼通常都很容易,團隊應該能創(chuàng)建出快速運行的單元測試。可是,團隊很可能會發(fā)現(xiàn),那些沒有自動化測試的代碼之間的依賴關系很亂。開發(fā)人員必須想辦法把他們正在寫的代碼從中隔離出來,然后才能給它們寫單元測試。可以在《修改代碼的藝術》[1]一書中找到一些相關的實效技巧介紹[Fea04]。
我們合作過的大多數(shù)團隊都從如下這條基本準則起步:為新代碼和遺留代碼的修改部分編寫測試。也可以跟團隊討論一下這種方式,看看他們是否愿意承諾照這樣做。如果遵循法則會有太大壓力,就跟他們約定,每天寫一兩個測試,這樣至少能保證有些進展。明確告知團隊,最有用的測試關注代碼中可能有問題的路徑,而不是那些無關緊要的方法。可別把目標設為給getter和setter寫測試,那不是關鍵。
團隊決定從哪塊代碼入手開始增加自動化測試之后,提醒他們還要商量好怎么組織這些測試。他們需要考慮把測試放哪里,是與代碼放在同一個子目錄里還是分開來。保持測試命名方式的一致性也很有幫助。最后一點也很重要,要讓團隊所有人都能夠順利運行整個自動化測試套件。
自動化測試 敏捷開發(fā)
版權聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權內(nèi)容。
版權聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權內(nèi)容。