1. 反饋
?反饋是我們認識世界常用的方法袭异。 我們先有一個模型(假設)钠龙,這個模型去解釋現(xiàn)象,然后再結合實踐或者實驗御铃,得到的實際結果與模型得到的期望結構對比俊鱼。如果一致,那么我們認知與外部世界一致畅买;如果有差異并闲,那么模型有誤,需要修正我們的大腦里面認知谷羞。 反饋幫助我們發(fā)現(xiàn)問題帝火,快速反饋可以幫助盡早的發(fā)現(xiàn)問題,從而更加容易糾錯湃缎。 如果缺乏這種快速反饋機制犀填,最終出錯了,到底哪里出錯嗓违,排錯的難度就大很多了九巡。 所以有很多種方法論都利用反饋機制。?
比如戴明環(huán)蹂季,PDCA:?
比如開發(fā)MVP模型:
比如敏捷開發(fā)迭代模型:?
基于這種反饋機制冕广,我們每一次迭代疏日,都通過反饋來檢驗,后面的迭代以前面為基礎撒汉。 隨著迭代次數(shù)增加沟优,構建模型也越來復雜,甚至復雜超出我們大腦容量(比如大型軟件不可能一次全部放入大腦去思考)睬辐。這個時候?qū)τ谀P偷男薷哪痈螅茈y發(fā)現(xiàn)問題。 潛在的思考不周全溯饵,狀態(tài)行為不一致侵俗,引入bug,甚至regression的風險就很大丰刊。 但是如果對于每一次修改竟终,都有反饋機制輔助我們來檢驗挪丢,那么風險就降低很多了营勤。 基于構建的模型战虏,可以認為是看做是生長的凫乖,一點一點長大洛巢,所謂基于反饋增長模型通铲;
另外一種則是線性的增長旺矾,線性模型(差之毫厘渣玲,謬以千里)
比如說瀑布開發(fā)模型中逗概,在需求源頭中有錯誤,在最終發(fā)布在客戶那里發(fā)現(xiàn)忘衍,那么這時候再糾正逾苫,那難度和成本與在開始發(fā)現(xiàn)時候相比,真是數(shù)量級的差異枚钓。
在軟件開發(fā)中铅搓,往往基于反饋比這種線性開發(fā)方式更容易控制。
2. 軟件開發(fā)中反饋
2.1 敏捷宣言遵循的12條原則搀捷,也是反饋具體表現(xiàn)星掰。
我們最重要的目標,是通過持續(xù)不斷地早交付有價值的軟件使客戶滿意嫩舟。
經(jīng)常地交付可工作的軟件氢烘,相隔幾星期或一兩個月,傾向于采取較短的周期家厌。
業(yè)務人員和開發(fā)人員必須相互合作播玖,項目中的每一天都不例外。
可工作的軟件是進度的首要度量標準
2.2 敏捷開發(fā)Scrum饭于。 下面圖中每一個環(huán)路都是一個反饋蜀踏。每一次反饋就是一次盡早發(fā)現(xiàn)問題的機會维蒙。
2.3 敏捷里面的工程實踐
比如CI/CD管道,對于每一次代碼的更改脓斩,甚至是配置文件的更改木西,對需要走一次反饋。 從代碼掃描随静,編譯八千,測試,部署燎猛, 每一步都是一次反饋恋捆。?
比如團隊之間反饋活動,code review, code inspection and pair programming重绷。?
再比如測試本身就是一種反饋沸停。經(jīng)典的測試金字塔( 單元測試,模塊測試昭卓,系統(tǒng)測試愤钾,探索性測試)都是不同層面的反饋,只是粒度不一樣候醒。
TDD 也是一種反饋能颁。 先寫測試用例,然后寫代碼倒淫;運行測試伙菊,去驗證代碼,這是一次反饋敌土;重構代碼镜硕,運行測試,也是一種反饋返干。
3. ?有效反饋的特點(早兴枯, 快,準確矩欠,可重復?)
反饋可以幫我們發(fā)現(xiàn)問題财剖,從而輔助我們糾正問題。 但是不是所有的反饋都是有效的晚顷。 比如說反饋時間太長峰伙,耽擱下一次迭代的時間;如果等不及反饋結果進行下一次迭代该默, 如果出錯瞳氓,不知道是這次迭代還是上次迭代出的錯。反饋不準確,得到不有有效信息排錯匣摘,丟到反饋部分價值店诗; 反饋結果不重復,那么反饋不可靠音榜,就會干擾正常工作庞瘸。 所以有效的反饋,需要有以下4個特點赠叼。
反饋早擦囊, 反饋的快,反饋的準確嘴办,反饋的可重復
早點得到反饋結果瞬场,如果有錯,這個時候修改距離上次修改比較少涧郊,在時間上距離上次修改間隔比較短贯被,容易排查錯誤,而且成本低妆艘。 只有反饋的快彤灶,反饋的結果才可以早點拿到。 反饋的準確性給予足夠的信息批旺,可以方便我們排查糾錯幌陕。而反饋結果的可重復性,一致性朱沃,才使得反饋有意義苞轿。
下面從這四個方面考察TDD中測試用如何做到茅诱。 當然這些原則對于其他軟件實踐也同樣適用,如CI/CD逗物,pair programming, 和軟件測試。
4. ?TDD 中如何構建有效的反饋
4.1 早反饋:
TDD是先寫測試用例瑟俭,再寫代碼翎卓,也就是test-first 。在沒有寫代碼之前已經(jīng)建立好反饋機制摆寄,與其他各種實踐在代碼寫之后再去驗證失暴,而言有更大的優(yōu)勢。 寫測試用例微饥,完全不用去考慮實現(xiàn)代碼逗扒,實現(xiàn)代碼壓根不存在,這樣寫出的代碼不受實現(xiàn) 影響欠橘,是一個黑盒子矩肩,測試與實現(xiàn)徹底解耦。這樣可以寫出來的測試沒有實現(xiàn)約束干擾肃续,更可以表達出來意圖黍檩。
4.2. 快反饋 ??
反饋結果要拿的早早叉袍,盡量減少測試執(zhí)行的時間。
計算機世界刽酱,要快當然是自動化喳逛, 自動化可以減少人為干擾。徹底自動化棵里,一鍵式自動化润文,一個命令所有的東西都運行。現(xiàn)在主流的語言就是這樣殿怜。比如maven转唉,gradlle.
另外測試用例執(zhí)行速度一定快,那么就要去掉或者減少對外部依賴延時稳捆;比如數(shù)據(jù)庫赠法,大文件讀寫,網(wǎng)絡乔夯;這些可以用test dump技術砖织,dump/mock 去替換現(xiàn)實世界中依賴。
增加機器末荐,并行執(zhí)行侧纯。如果當test case 很大的情況,并行執(zhí)行甲脏,加速執(zhí)行過程眶熬;
測試影響分析; ?但是還有另外一個思路块请,每一次代碼的修改娜氏,不需要運行所有的測試用例;那么怎么選測試用例墩新,使得不多不少贸弥,從而減少哪些不需要的測試用例的執(zhí)行,也可以大大的減少執(zhí)行的時間海渊。參見绵疲,減少無用測試用例的執(zhí)行,從而提高執(zhí)行速度臣疑。
4.3 ?準確反饋 -- 減少干擾
測試如果出錯盔憨,要很明白的告訴哪里出錯,這樣很容易幫助我們定位問題;而不是含糊其詞unknown error讯沈,segment error郁岩。所謂準確,就是當測試失敗的時候,下面這些信息是很容易得到的
1. 這個測試用例測試什么場景驯用?
2. 這個測試用例的測試點是什么脸秽??
3. 這個測試用例的輸入,輸出蝴乔,和期望輸出是什么记餐?
4. 這個輸出與期望輸出,有哪些不同薇正?
如果這些信息都可以很準確的獲得片酝,如果剛修改的代碼上下文還沒有忘記,大概就可以推測出代碼出錯的地方挖腰。 不就是剛才修改的地方雕沿??
但是這里有一個前提是,測試用例一定容易理解猴仑。那么怎么才能容易理解审轮? 測試名字,需要認真考慮辽俗,需要體現(xiàn)測試場景和意圖疾渣; ?測試點,可以用assert來顯示刻畫崖飘。理想情況下一個測試用例一個測試點assert榴捡。如果有太多的,那么測試意圖就不明顯朱浴。這個時候應該考慮將這個測試用例分解多個測試用例吊圾,不同的關注點不一樣。測試用例也需要考慮職責單一原則翰蠢。
更進一步项乒,結構化的寫測試用例可以幫我們理解。 結構化的測試用例分四部分:設置參數(shù)躏筏,調(diào)用方法板丽,驗證期望呈枉,清理現(xiàn)場趁尼。 對于每一個測試用類似的結構化模板統(tǒng)一寫,方便查找和理解猖辫。
再進一步酥泞,如果有準確的錯誤信息那么重要,為什么不利用反饋機制讓錯位更清晰準確啃憎? 那么 TDD可以變成這樣樣子:
4.4? 重復反饋 -- 環(huán)境隔離
重復芝囤,這里指的是如果測試結果一致性,每一次運行結構都一樣。 對于不同人悯姊,不同機器羡藐,不同的時間,運行結果是一致的悯许。 這樣的測試結果才是可靠的仆嗦,所有人都信任的。 這樣較少誤報先壕,減少干擾瘩扼。
如果測試結果不一致,大多是是外部環(huán)境導致的垃僚。比如隨機說集绰,時間,網(wǎng)絡谆棺,第三服務栽燕,操作系統(tǒng)等等都可能產(chǎn)生潛在的不一致。 一方面減少對環(huán)境的依賴改淑,另外一方面使得測試環(huán)境標準化纫谅。虛擬機或者容器很大程度幫助我們減輕環(huán)境的不一致。
5 小步慢走溅固,和快速反饋和回退重來相結合付秕。?
小步慢走,分解是核心侍郭;將一個大的task分解為小的任務询吴,對于每一個小任務更好的控制。 快速反饋亮元,可以讓我們及時發(fā)現(xiàn)偏差猛计; 同時, 快速反饋機制爆捞,可以 幫你監(jiān)控regression奉瘤,減輕大腦負擔,讓大腦專注于當前的工作煮甥。 如果出錯盗温,因為每一次改的小,排查錯誤的范圍谐芍狻卖局; 同時反饋的及時,在大腦沒有遺忘上下文的時候就可以很快展開糾偏工作双霍,高效砚偶。 另外批销,如果每一次的小步都有保存,那么我們還有一個回退按鈕染坯,給我重來的機會均芽。
將三者相結合,這樣的方式去寫代碼单鹿,就可以鼓勵去修改骡技,大膽的修改,放心的修改羞反,有信心去修改布朦,終于奔向自由飛翔了。
之前提到過一個工具cyber-dojo昼窗, 刻意練習TDD工具是趴。集成?小步快走(分解),快速反饋(TDD)澄惊,同時任何時候運行會保存下來唆途,提供回退機會。 如果刻意練習掸驱,應該嘗試一下肛搬。