開發(fā)者測試:可測試性是設(shè)計(jì)出來的

談開發(fā)者測試,為什么又要談設(shè)計(jì)呢?這是一個(gè)有意思的問題。在切入這個(gè)主題之前,先看一個(gè)“完美架構(gòu)圖”的問題。

架構(gòu)是完美的,實(shí)現(xiàn)是骨干的

我相信你肯定看過無數(shù)多個(gè)類似這樣的架構(gòu)圖,每個(gè)框框都排布整齊,而且顯得特別高大上。

引自:架構(gòu)就是畫框框?熊節(jié)

但是,實(shí)際的系統(tǒng)實(shí)現(xiàn)真的是這樣嗎?未必。系統(tǒng)往往充滿了各種變化、約束、限制和條件,這些隱式的概念往往是不能“公諸于世”的。設(shè)計(jì)存在就是為了控制住系統(tǒng)實(shí)現(xiàn)的復(fù)雜度,應(yīng)對(duì)軟件的變化,并將這些隱式的概念顯式化。

但是,我們也不能否認(rèn)架構(gòu)存在的意義,至少它利于個(gè)體之間的交流,利于與客戶的溝通,并在更高維度的角度看待問題,并指導(dǎo)進(jìn)一步的系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)。

分層架構(gòu)

理論上,任何復(fù)雜的系統(tǒng)都可以用一個(gè)main函數(shù)實(shí)現(xiàn),但事實(shí)上沒人那么干,分層架構(gòu)便是一種最樸素的系統(tǒng)分解和組合的架構(gòu)思維,并符合大部分人的心智模型。

分層架構(gòu)

分層架構(gòu)最大的好處在于提供了層間抽象和隔離的機(jī)制,并非常容易在工程上保證層間的契約不被破壞。例如,分層架構(gòu)遵守單向依賴原則,當(dāng)有人違背架構(gòu)原則而引入循環(huán)依賴,采用一些架構(gòu)看護(hù)的工具,使能自動(dòng)檢查這些行為的。

其次,分層架構(gòu)有利于開展模塊間并行開發(fā)和協(xié)作。每個(gè)模塊只要邊界清晰,便可以獨(dú)立開發(fā)了。但是,任何的軟件工程方法的實(shí)踐,必然存在它的邊際效應(yīng)。

同層模塊間依賴混亂、模塊內(nèi)實(shí)現(xiàn)一團(tuán)亂麻,

這是很多系統(tǒng)實(shí)現(xiàn)的真實(shí)寫照。雖然,層間調(diào)用和約定都得到了很好的約束和保證,但同層內(nèi)的模塊間的耦合程度極高,相互引用和依賴,缺失架構(gòu)原則的約束和檢查。

更有甚者,模塊內(nèi)實(shí)現(xiàn)基本都是基于全局變量的過程化設(shè)計(jì),缺失最基本的封裝。在面臨變化的時(shí)候,要么就是堆砌if-else,要么大面積拷貝代碼,修修補(bǔ)補(bǔ),導(dǎo)致系統(tǒng)實(shí)現(xiàn)的耦合度急劇攀升,最終將系統(tǒng)成功演進(jìn)為典型的“腐化系統(tǒng)”。

系統(tǒng)實(shí)現(xiàn)的現(xiàn)狀

設(shè)計(jì)邊界

當(dāng)我們確定了設(shè)計(jì)的邊界和范圍,便自然地決定了軟件工程效率提升的邊界、獨(dú)立測試的邊界、獨(dú)立構(gòu)建的邊界,及其獨(dú)立可替換的設(shè)計(jì)邊界。

設(shè)計(jì)邊界

邊際效應(yīng)

任何流程、工具和機(jī)器提升效率的邊界,約束在設(shè)計(jì)邊界的最大效應(yīng)內(nèi),無法跨代提升。唯有改進(jìn)設(shè)計(jì),將設(shè)計(jì)的邊界往內(nèi)遷移,相應(yīng)的工程效率才能得到質(zhì)的提升和飛越。

邊界等同

設(shè)計(jì)邊界即獨(dú)立裁剪的邊界,獨(dú)立測試和獨(dú)立交付的構(gòu)建邊界。如果層間之間的依賴是抽象的,那么層測試所依賴的其他層實(shí)現(xiàn)便可以替換為測試替身;如果層內(nèi)模塊之間是低耦合的,那么模塊測試所依賴的其他模塊也可以替換為測試替身;如果模塊內(nèi)類或函數(shù)之間是低耦合的,那么類或函數(shù)所依賴的其他類或函數(shù)也可以替換為測試替身。

設(shè)計(jì)優(yōu)先

因此,可替換性(裁剪性)、可測試性是提前設(shè)計(jì)出來的,是由設(shè)計(jì)的邊界決定的,這便是"Design for Testability"的原始初衷。

測試金字塔

因?yàn)樵O(shè)計(jì)的邊界決定了測試的邊界。正如上述的系統(tǒng)實(shí)現(xiàn),如果將系統(tǒng)看成整體,其外部的依賴和可觀察的行為是可以控制的,所以設(shè)計(jì)相應(yīng)的系統(tǒng)測試,雖然復(fù)雜,而且極難構(gòu)造,但它是一種較為可行的測試方案。所以,這也是遺留系統(tǒng)普遍采用的一種測試方案,產(chǎn)生了大量的ST用例。

層間接口也較為穩(wěn)定,所以也可以構(gòu)造出大量的IT用例;而層內(nèi)模塊之間耦合程度逐漸增大,所以CT用例越來越少;隨著設(shè)計(jì)邊界的邊際效應(yīng)的消失,模塊內(nèi)的單元測試構(gòu)造成本很高,或測試用例很脆弱,大部分系統(tǒng)實(shí)踐單元測試最終走向了不歸路。

最終,實(shí)際的測試金字塔是倒立的,或呈現(xiàn)菱形。與理想的測試金字塔剛好相反或背道而馳。

測試金字塔

理論上,UT是容易構(gòu)造的,而且反饋是急快的,而且應(yīng)該擁有絕對(duì)數(shù)量的UT用例。但是,現(xiàn)實(shí)并非如此,構(gòu)造的UT并非易事;實(shí)現(xiàn)可能依賴龐大的全局變量,函數(shù)入?yún)⒌慕Y(jié)構(gòu)體包含了繁雜的字段,而且函數(shù)實(shí)現(xiàn)朝夕令改,導(dǎo)致用例極為脆弱。

就其本質(zhì),這都是設(shè)計(jì)的問題。如果將每個(gè)全局變量進(jìn)行合理的封裝,那么內(nèi)部邏輯變得更加穩(wěn)定,測試用例的前置條件也變得容易構(gòu)造;如果將不必要的依賴剝離,將實(shí)現(xiàn)最小化依賴,測試用例也會(huì)變得更加健壯;如果將依賴設(shè)計(jì)為抽象的,那么在測試中便可以輕松地替換為測試替身,提升可測試性。

總而言之,可測試性是設(shè)計(jì)出來的(Design for Testability)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、 軟件測試基本概念 1 bug的概念 bug類型:defect、fault、problem、error… pr...
    三口一個(gè)瓜閱讀 4,026評(píng)論 0 12
  • 最近再看阮一峰的一篇博客提到了一本書《Software Architecture Patterns》(PDF),寫...
    卓_然閱讀 8,254評(píng)論 0 22
  • 序 程序員的三個(gè)層次(1) 普通程序員編寫代碼,能夠讓程序跑起來的人。(2) 工程師有“潔癖”、有工匠精神、有修養(yǎng)...
    nimw閱讀 1,783評(píng)論 0 3
  • 這幾天參加今年公司年會(huì),自己也參加了一個(gè)節(jié)目、臺(tái)詞不多客串了一下甲方。晚餐餐食不錯(cuò),和幾個(gè)銷售同事都沒喝酒,安心吃...
    Aichris閱讀 237評(píng)論 0 0
  • 我們很多時(shí)候,行事為人看別人的臉色,采用別人的建議,往往忽略了自己的感受,埋沒了自己的思想,成了?一個(gè)為別人...
    朱紅玲閱讀 491評(píng)論 6 17

友情鏈接更多精彩內(nèi)容