我曾經(jīng)咨詢輔導(dǎo)過的一家企業(yè),研發(fā)儀表產(chǎn)品,其嵌入式軟件不是很復(fù)雜,因此, 采用的CPU檔次不高,軟件的編譯環(huán)境不具備調(diào)試功能,每次代碼寫好、編譯、燒片后才能驗(yàn)證軟件功能。通常,編好的軟件會(huì)埋藏一些bug,由于只能燒片后才能發(fā)現(xiàn)這些bug,而且編譯環(huán)境又沒有調(diào)試功能,工程師只好憑著猜測嘗試修改缺陷,然后再燒片把軟件下到設(shè)備中驗(yàn)證來bug的修復(fù)情況,據(jù)估計(jì)有時(shí)他們一天要燒片三十多次,花掉了大量的時(shí)間。
最近,漢捷又遇到了一家產(chǎn)值近百億的高科技企業(yè),他們的產(chǎn)品開發(fā)出現(xiàn)了軟、硬件相互等待的現(xiàn)象,即軟件需要硬件電路板先做好,讓軟件可以上板調(diào)試,而硬件又要求軟件先做好,才可以對硬件電路板進(jìn)行硬件功能測試。這樣相互依戀的關(guān)系,導(dǎo)致彼此等待、相互沖突扯皮,最后項(xiàng)目延期。
上面兩個(gè)案例,估計(jì)很多企業(yè)都遇到類似的情況,有沒有什么方法可以解決呢?有,軟件單元測試。
在國內(nèi),鮮有企業(yè)的軟件開發(fā)人員做單元測試,不會(huì)做,更不想做。不想做的理由是:項(xiàng)目的進(jìn)度這么緊張,哪里有時(shí)間做單元測試啊,或者,要做單元測試豈不是還要多招一些軟件工程師,不劃算!
真的是這樣嗎?十多年前,我在華為北研所帶領(lǐng)一個(gè)團(tuán)隊(duì)負(fù)責(zé)一款產(chǎn)品的軟件開發(fā)工作,我本人也承擔(dān)了其實(shí)一部分底層驅(qū)動(dòng)的開發(fā)工作。我們這個(gè)項(xiàng)目當(dāng)時(shí)是北研所首批的IPD-CMM流程試點(diǎn)項(xiàng)目,從需求到設(shè)計(jì)再到編碼都是有條不紊地進(jìn)行著,各個(gè)模塊的代碼編寫完成后,不僅要經(jīng)過嚴(yán)格的代碼review,之后還要做單元測試。以底層驅(qū)動(dòng)模塊為例,軟件和硬件有接口,最直接的接口就是兩個(gè)讀寫硬件寄存器的函數(shù)。驅(qū)動(dòng)的單元測試,指的是在既不上硬件、也不跑上層應(yīng)用的環(huán)境下,對驅(qū)動(dòng)軟件模塊進(jìn)行的獨(dú)立測試。我們在PC機(jī)的VC++集成開發(fā)環(huán)境下做驅(qū)動(dòng)代碼的單元測試,把這兩個(gè)寄存器讀寫函數(shù)置換為樁(stub)函數(shù)(也就是形式上相同的假函數(shù)),并通過開一塊內(nèi)存區(qū)或一個(gè)全局變量數(shù)組來模擬寄存器。通過VC++可視化編程的便利性生成圖形界面,非常方便地執(zhí)行各項(xiàng)功能操作和查看單元測試結(jié)果。經(jīng)過了單元測試,非常便捷地發(fā)現(xiàn)了許多軟件自身的bug,之后再和硬件進(jìn)行集成測試,暴漏的更多的是軟硬件接口問題和硬件自身問題,大大縮短集成的周期,因?yàn)橐皇侨毕萆?,二是缺陷定位容易,減少了軟硬件溝通成本。單元測試雖然要花費(fèi)一定的時(shí)間,然而它卻成倍地縮減了系統(tǒng)測試時(shí)間。該項(xiàng)目到系統(tǒng)測試階段,測試工程師測了不到一周時(shí)間,就很難能發(fā)現(xiàn)問題了,而以往沒有做過單元測試的項(xiàng)目,測上一個(gè)月都不放心。
從那個(gè)項(xiàng)目結(jié)束后,我開始愛上了軟件單元測試,特別是有與硬件有接口的驅(qū)動(dòng)軟件,哪怕硬件電路板準(zhǔn)備好,我也要求軟件工程師必須在方便快捷的PC機(jī)環(huán)境下先做好單元測試。在當(dāng)時(shí)的華為北研所,越來越多的軟件工程師也漸漸由開始的抵觸造單元測試,到后來接受認(rèn)可,因?yàn)橛写罅繉?shí)際項(xiàng)目數(shù)據(jù)和案例證明,做單元測試不是延遲了項(xiàng)目進(jìn)度,而是縮短了項(xiàng)目進(jìn)度,同時(shí)也提升了產(chǎn)品質(zhì)量。如,我們從實(shí)際項(xiàng)目統(tǒng)計(jì)數(shù)據(jù)來看,經(jīng)過單元測試發(fā)現(xiàn)和解決一個(gè)缺陷所需要的工作量是單位1,則經(jīng)過系統(tǒng)測試發(fā)現(xiàn)和解決一個(gè)缺陷需要的工作量是單位6。為什么單元測試會(huì)超人意料地高效呢?僅從一個(gè)方面來看好了,做過軟件的都知道,有時(shí)系統(tǒng)測試發(fā)現(xiàn)的問題,開發(fā)人員可能一個(gè)月還無法定位,而單元測試測的是各個(gè)函數(shù),基本不存在定位問題,自然不存在耗費(fèi)在定位缺陷的時(shí)間了。
如今軟件單元測試在華為早已成為一種如洗臉?biāo)⒀腊愕牧?xí)慣。然而,我從事咨詢工作六年來,去過四十多家企業(yè),很少能看到有哪家企業(yè)做且有效地做軟件單元測試,實(shí)為遺憾!不必說剛畢業(yè)的學(xué)生們,就是從業(yè)多年的軟件開發(fā)管理者也對單元測試存在著嚴(yán)重的誤解。如果能把單元測試有效做起來,案例中,做儀表的軟件工程師就不必每次寫完代碼,浪費(fèi)大量時(shí)間去燒片測試,完全可以在PC機(jī)上把邏輯處理、計(jì)算等與硬件不相關(guān)的軟件實(shí)現(xiàn)進(jìn)行充分地驗(yàn)證。軟件開發(fā)人員寫完驅(qū)動(dòng)代碼后,不必等待硬件電路板到位才讓你的代碼跑起來,通過單元測試的打樁方式,把軟件和硬件先剝離開,同樣可以讓代碼運(yùn)行起來,而且更便捷,硬件很難發(fā)生的情況,在這樣的模擬環(huán)境卻很容易構(gòu)造出了,因此,也就解決了軟、硬件互等的鎖死現(xiàn)象。
漢捷曾輔導(dǎo)軟件單元測試的一家臺(tái)灣企業(yè),老總曾在美國TI工作,做IC出身,深知單元測試的重要性,他說:“IC每次流片就要花掉幾百萬、上千萬美金,因此IC工程師在流片前不得不做詳盡的單元測試,而做軟件的好像不必付如此大的代價(jià),因而就不做單元測試了,理由是項(xiàng)目很緊張,可是大家卻有時(shí)間不斷地事后返工!”
我想,如果我們的企業(yè)老總、研發(fā)總監(jiān)對于軟件單元測試認(rèn)知程度如這家臺(tái)灣企業(yè)老總那般深刻,那么軟件單元測試就不會(huì)僅僅作為理論停留在軟件工程教科書上,它會(huì)鮮活地走進(jìn)項(xiàng)目里,成為一種實(shí)實(shí)在在的讓項(xiàng)目進(jìn)度加速的給力的實(shí)踐活動(dòng)!