一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

TDD到底美不美?

  最近CoolShell上的一篇《TDD并不是看上去的那么美》引起了敏捷社區的高度關注和激勵辯論。今天,InfoQ甚至專門舉行了一個虛擬座談會《TDD有多美?》,幾位國內敏捷社區的名人專門就此問題展開了深入地討論。不論結果如何,這種探討和反思的精神還是非常值得贊賞的。事件實際上可以簡單地歸納為一個有一定影響力的開發人員質疑TDD,一群敏捷社區名人對TDD進行解釋和辯護。現在,就讓我堅定地站在CoolShell一邊,為對TDD的質疑和批判添磚加瓦吧!

  我們首先來看看TDD的核心理念是什么。第一是用例即規范(Specification by Example),即把測試用例作為需求規范的一種形式。傳統的需求表達方式包括文檔,Use Case等,而TDD強調通過測試用例來表達需求。另外,TDD的測試用例是黑盒的基于外部接口的,所以,它實際上又是對外部接口的設計。不把測試用例單純地視為測試,而從需求和設計的角度來看測試用例是TDD與傳統測試的一個重要區別。TDD的第二個重要理念是Test First,強調測試對于實現的驅動作用,先寫測試用例,再實現和重構。Test First的實質是先理解清楚需求,并做好外部接口設計,把它轉化為測試用例,然后再來實現和重構。

  如果說用例即規范還彌補了文檔和Use Case在表達需求時的某些不足,具有一定的好處,那么Test First則有很大的問題,尤其在沒有測試用例失敗之前,不要寫任何一行代碼的極端方式則更是極端的錯誤。

  如果測試用例就是需求和設計,那么為什么不能先寫出測試用例再來實現呢?這不是我們最熟悉的先需求再設計再編碼嗎?答案是:不能執行的測試用例(Test First)和能執行的測試用例有著天壤之別,你寫出了測試用例不代表你就看到了運行的實際效果。

  不能執行的測試用例和寫在紙上的文檔相比對實現的指導意義不見得能好到哪里去!除非是一些很簡單的情況下,在實際的軟件開發中,你很難在沒有執行測試用例的情況下寫出真正符合最終需求的測試用例來。比如:你做一個頁面,頁面的效果需求和設計通常會在真正可以運行之后不斷調整,在實現之前只能有一個大致的輪廓和方向,許多方面的細節要么是沒想清楚,要么是完全沒想到,不可能一蹴而就。如果片面強調測試對實現的驅動作用,那么實際上隱含了需求和設計的細節可以在實現之前明確下來的假設,這是非常不敏捷的和不現實的!

  Test First要求寫測試用例時對軟件需求有精確的了解,但實際軟件開發過程中用戶需求和外部環境的不確定性會導致軟件需求難以把握和頻繁變動。

  用戶需求的不確定性是指需求無法在用戶真正能運行看到效果之前明確下來。比如:讓你開發一套Wow這樣大型的游戲,你能想象游戲的效果是設計者一開始就想好了精確到每一個細節嗎?對于游戲這樣的軟件,需求和設計不可能脫離實際運行紙上談兵地產生。游戲的設計者通常只能借助文檔、草圖、Use Case等非精確的方式大致提出需求,先做出原型,在看到效果之后才能逐步地細化和明確,需求設計的增加和改變會伴隨整個軟件開發過程。

  另外,還有一種極端的情況是根本不存在精確的用戶需求,比如:自動化翻譯軟件,你能在實現之前就把翻譯效果用測試用例固定下來嗎?存在絕對正確的翻譯方法嗎?最近,我們和國外一家大公司客戶談一個項目需求的時候,客戶講了這樣一句話我們現階段還無法提出很細致的需求,只有等你們拿出第一個版本,然后我們再逐步地調整細化。我們的客戶沒有宣稱自己在做敏捷,但人家的思維方式多敏捷啊,不是什么一上來就明確需求,而且還要精確寫出自動化測試用例。有人說這種情況我們仍然可以先根據自己的理解進行TDD,這樣做可以:

  1. 基于測試用例和客戶溝通明確需求;

  2. 驅動實現。我對此持不同看法,能執行的測試用例和不能執行的測試用例有著天壤之別,客戶從測試用例根本無法獲得真實運行的體驗,你能想象蘋果把iPhone的測試用例寫在PPT上,給用戶做一個演講,用戶就能給出關于iPhone設計的反饋了嗎?要真正的用戶反饋,就需要實打實的軟件,這不正是敏捷的Working software over document的思想嗎?另外,既然用戶無法在實際體驗之前提出反饋,那么開發人員在開發初期做的需求分析和設計都只是一個探索,隨時可能調整甚至被推翻,不值得在實現之前進行自動化測試設計的投資。

  外部環境的不確定性是指"當我們的系統需要和外部系統集成時,關于外部系統行為的假設也無法在實際集成運行前完全確定"。例如,要做一套股票客戶端連上交易所系統,因為交易所的行為會直接影響到客戶端的開發,所以只有在弄清交易所行為的情況下才談得上開發出高質量的客戶端。如果采用測試驅動,編寫了各種涉及交易所行為的測試用例,比如什么情況下發什么類型的消息,消息格式如何,如何交互等等,但是這些測試用例本身是否正確卻需要打一個大大的問號!這一方面是由于很多交易所提供的協議都不夠清晰或者有許多未明確定義的地方;另一方面即使協議沒有問題,開發人員也可能由于單純的失誤或者缺乏相應領域的基本知識而把協議理解錯。

  實際上,要真正弄清交易所的行為明確客戶端的需求,最重要的手段還是在交易所提供的測試環境中跑集成測試。對于Test First來講,測試用例本身的錯誤可以說是代價最大的,不僅浪費時間和精力,更重要的是還打擊開發人員的士氣,誰愿意來回折騰呢?但很不幸,實際情況是在最初沒有明確交易所行為的時候Test First出來的測試用例隨時可能在真實集成后被推翻,并且如果是比較高層的需求分析失誤,那對整個架構設計來講會是災難性的后果。在實際開發中,我們的軟件需要和其他系統集成的情況是非常普遍的,而期望在沒有進行實際集成的情況下弄清外部系統的行為都是不現實和不敏捷的。

  所以,Test First需要對于被測系統的需求和環境有精確的了解,但由于需求不確定性和外部環境不確定性兩大問題,Test First在很多時候都是不現實的。其實,Test First和瀑布式思想一脈相承,都強調需求先于實現,而忽略了軟件需求的產生會受到實現的反饋,會在實際運行中不斷調整探索完善。TDD無非是把需求分析的結果用測試用例表達,替代傳統用文檔表達需求,但從宏觀上看,TDD和瀑布比是換湯不換藥,這都不是真正的敏捷。

  除了簡單情況,不存在脫離實現的需求,你能夠在明確了需求之后就實現出一套Linux系統嗎?既然你根本無法實現一套Linux系統,那么這樣所謂的需求又有多大的意義呢?所以,能提出什么樣的需求不能脫離你的實現能力。需求和實現之間不是簡單的誰驅動誰,而是一種相互反饋的關系,這與需求用什么方式表達沒有關系。正如瀑布模型無法在初始階段做出完美的需求分析,TDD也無法在初始階段做出完美的測試用例;不僅如此,自動化測試用例的開發維護成本還遠高于文檔。

  所以,在敏捷環境中,軟件開發初期應該通過文檔和用例等手段大致表達需求,實現之后在實際運行中體驗效果,不斷優化探索和明確需求和外部環境,當需求和對外部環境的認識達到一個比較穩定的程度才編寫測試用例將需求固化下來。

  上面的論述主要針對貼近最終用戶的外部需求(如ATDD),下面我會進一步解釋即使是在內部的單元測試級別TDD仍然有問題。我們還是首先從需求入手,思考一下單元的需求是哪里來的呢?答案是:需求來自于設計!比如,對輪胎的需求來源于汽車的設計,低層模塊的需求來源于高層模塊的設計。

  而在開發初期,這種內部設計具有很大的不穩定性,帶有很多假設的成分,在沒有進行集成測試的情況下,很難講這種內部設計是否合理。實際項目開發通常會在集成運行之后不斷調整內部的設計,即影響單元的需求。那么,如果是測試驅動,首先按不成熟的內部設計把一個個單元需求編寫成單元測試再來實現,實際上大大推遲了能進行集成測試的時間,對于真正快速弄清高層需求穩定設計反而是不利的。

  假設最終還是所有單元都完成,然后開始運行集成或驗收測試,這時候有兩種可能:

  1. 用戶看到實際效果,決定調整需求;

  2. 發現集成前在單元層面的假設不成立或者是有沒有考慮到的情況。不論是哪一種情況發生,以前所寫的單元測試都面臨著被廢棄或必須修改的命運。實際上,多數與業務相關的單元測試用例比起集成或驗收測試用例更加不穩定,因為它會受到所有其上層模塊的需求和設計變動的影響。

  由于我們在不穩定的單元測試上浪費了大量的時間(按我的經驗編寫單元測試比編寫實現更耗時),這就導致了遲遲無法進行集成看到實際效果,也沒有辦法敏捷地應對需求的調整。也就是說具有諷刺意味的,Test First理念居然是和敏捷理念矛盾的!
  所以,我認為Test First不符合敏捷開發的基本假設,而真正符合敏捷的理念是需求和設計依賴于實現的反饋,需要在實際運行過程中根據效果不斷探索調整得來的,不可能脫離實際運行寫出真正符合最終需求的測試用例來。所以,我們真正應該做的是盡快看到實際運行的效果,而自動化測試作為固化的需求和設計是在看到效果之后。在集成之前花太多精力進行測試驅動只會導致遲遲看不到實際運行效果(尤其是基于開發人員自己的假設編寫大量單元測試用例),看到效果需要調整需求又會廢掉或改掉一大堆的測試用例。

  實際上,越是外部的需求其變更帶來的影響和代價越大,越是需要盡早明確。從宏觀上看,TDD所謂的快速反饋實際上是加快內部反饋,延遲了外部反饋,這無異于本末倒置。而大量需要修改或作廢的測試用例其實是一種很大的浪費,這和消除浪費的精益思想也是矛盾的!

  上面這幅cost/length_of_feedback_cycle圖是我們常見的用于說明敏捷方法比傳統方法具有更短的反饋周期,更小代價的應對變化。從圖中我們可以清晰的看到在驗收測試中發現的需求錯誤導致的代價是最高的。如果驗收測試往后推遲一點,發現錯誤的代價將按非線性地增長。上面我們已經論述了,任何方法都不可能消除驗收測試后對需求的調整,因為這是需求產生的正常過程。

  我們唯一可以做的是盡可能地縮短驗收測試的反饋周期,但是很不幸TDD大量的內部測試只會導致推遲驗收測試的時間,從而大大增加代價。在實際開發中,我提倡在第一次集成運行測試之前不要寫單元測試用例;自動化的驗收測試用例則視編寫和維護的代價而定,如果代價比較高,則應該采用文檔和Use Case來描述需求,因為這兩種方式比自動化的驗收測試更容易維護。編寫單元測試一定是在集成以后,這樣才能首先得到外部反饋,盡量先保證做正確的事情,再正確地做事。

  下面這段話來自于InfoQ文章《Mock不是測試的銀彈》:在使用JMock框架后測試編寫起來更容易,運行速度更快,也更穩定,然而出乎意料的是產品質量并沒有如我們所預期的隨著不斷添加 的測試而變得愈加健壯,雖然產品代碼的單元測試覆蓋率超過了80%,然而在發布前進行全面測試時,常常發現嚴重的功能缺陷而不得不一輪輪的修復缺陷、回歸 測試。為什么編寫了大量的測試還會頻繁出現這些問題呢? 這描述的情況和我在實踐中遇到的情況類似,不過很可惜文章并沒有找到問題真正的原因。

it知識庫TDD到底美不美?,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

主站蜘蛛池模板: 激情综合网五月 | 在线播放亚洲美女视频网站 | 欧美色域 | 国产精品一国产精品免费 | 啪啪色网| 好吊操在线观看 | 亚洲国产成人精品小蝌蚪 | 婷婷婷色| 久久www免费人成看片色多多 | 四虎影永久在线观看网址 | 伊人久久大香线蕉综合7 | 成人免费在线视频 | 成人午夜视频免费 | 精品在线91 | 天天综合网天天综合色 | 美女被男人扒开下面无遮无挡 | 日韩欧美精品一区二区三区 | 免费一级做a爰片性色毛片 免费一看一级毛片人 | 日韩美女一级毛片 | 狠狠综合欧美综合欧美色 | 中国特级黄一级真人毛片 | 婷婷社区五月天 | 国产在视频线精品视频www666 | 91精品视频在线观看免费 | 日韩精品一区二区三区中文 | 永久免费av网站 | 一区二区三区四区在线不卡高清 | 国产夫妻av| 伊人狠狠干 | 亚洲欧美国产精品 | 国产精品女 | 亚洲国产欧美国产第一区二区三区 | 在线亚洲精品中文字幕美乳 | 亚鲁鲁国产 | 超人碰碰碰人人成碰人 | 色黄视频 | 男女男精品视频免费观看 | 欧美色域 | 久久lu| 高清国产美女一级a毛片录 高清国产美女一级毛片 | 青热久思思 |