android 源碼下載部分單元測試代碼分析

引自我的博客:android 源碼下載部分單元測試代碼分析

最近因?yàn)闃I(yè)務(wù)需要,在研究android源碼的下載部分。因?yàn)橐紤]代碼質(zhì)量的問題,所以就針對源碼的測試用例做了一些分析,并在源碼用例的基礎(chǔ)上添加了我們自己增加接口部分的用例。測試代碼的分析比較偏門,網(wǎng)上也很少見,這里權(quán)作探討,歡迎糾錯(cuò)。

在分析這個(gè)代碼之前,能想到的一些問題:

1.下載這部分涉及到網(wǎng)絡(luò)環(huán)境、數(shù)據(jù)庫、contentprovider、廣播等依賴硬件或外部環(huán)境較多的部分,如何測試;

2.網(wǎng)絡(luò)環(huán)境復(fù)雜多變,如何能夠測試全面;

3.我們了解下載系統(tǒng)的復(fù)雜程度,是以DownloadService為核心控制下載任務(wù)的刷新,

DownloadProvider供增刪改查各種任務(wù)為基礎(chǔ),供app用戶管理下載任務(wù)、查詢下載進(jìn)度和狀態(tài),真正下載的實(shí)現(xiàn)則在DownloadThread中——這樣一個(gè)復(fù)雜的模塊的測試從何下手。

然后,大體分析一下測試源碼的結(jié)構(gòu),我使用EA導(dǎo)入代碼工程的方式生成了類圖,再大體調(diào)整了一下位置布局,很方便。


來仔細(xì)分析一下測試源碼的類結(jié)構(gòu):

1. 以繼承關(guān)系為骨架看的話,可以分為三層,很明顯抽象類是不能直接作為干活的測試類的,繼承關(guān)系中的葉子節(jié)點(diǎn)類才是真正跑用例的類。那么其余部分肯定是為跑測試做各方面的準(zhǔn)備;

2. 最基礎(chǔ)的 AbstractDownloadProviderFunctionalTest,是第一層的中心。左邊兩個(gè)是它的內(nèi)部類,并且還維護(hù)著這兩個(gè)內(nèi)部類的實(shí)體;右面是對下載系統(tǒng)源碼中SystemFacade的一個(gè)模擬實(shí)現(xiàn)類的依賴,同樣維護(hù)著一個(gè)實(shí)體;在看各位組件的類名:TestContext、MockContentResolverWithNotify、FakeSystemFacade,可以說是假貨一條街??偨Y(jié)來說,第一層就是以AbstractDownloadProviderFunctionalTest為中心的組合關(guān)系,該類維護(hù)了一系列假貨的實(shí)體,那么大概齊是什么功能也能猜個(gè)八九了,具體是怎樣還要讀源碼來驗(yàn)證;

3. 第二層在繼承前類的同時(shí)又有拓展。該層已經(jīng)有一個(gè)葉子類了,DownloadProviderFunctionalTest,從一些共有方法能看到測試用例的定義,同時(shí)根據(jù)類名也能看出一二;AbstractPublicApiTest則是它的兄弟類,繼續(xù)抽象,仔細(xì)一點(diǎn)可以看出這里添加了一個(gè)重要的實(shí)體:DownloadManager,繼續(xù)做準(zhǔn)備吧,至于它的內(nèi)部類Download結(jié)構(gòu)上看不出什么,還需要看接口和源碼才能了解具體功能;

4. 第三層,就都是葉子類了,也是大規(guī)模測試用例的聚集地。在前面兩層的準(zhǔn)備之后,可謂萬事俱備,PublicApiFunctionalTest、ThreadingTest,看名字就知道了。

5. HelpersTest 該類是個(gè)閑散人員,不依賴任何環(huán)境的模擬。所以可以猜測是測試純功能函數(shù)的。

了解了大體結(jié)構(gòu)之后,就需要讀源碼了。走讀一下源碼,不多,大概不到1500行的樣子。然后就可以拿到大體上每個(gè)類都做了什么,如下:

1. AbstractDownloadProviderFunctionalTest 是基礎(chǔ)抽象類,這里完成了context、systemFacade、server、contentResolver等基礎(chǔ)環(huán)境的假冒偽劣活動(dòng),同時(shí)提供了偽造服務(wù)器響應(yīng)的方法供子類使用;

2. AbstractPublicApiTest 是上面那位的子類,同樣是抽象的,這里封裝了以DownloadID為核心的內(nèi)部類Download供后續(xù)斷言使用;引入了DownloadManager的工具實(shí)體,同時(shí)提供了偽造客戶端請求的各種方法供子類使用;

3. DownloadProviderFunctionalTest 繞開了對DownloadManager的測試,它使用暴力插入數(shù)據(jù)庫的方法添加下載,單純的測試下載器的功能,所以它只繼承了①;

4. PublicApiFunctionalTest 主要是針對DownloadManager的功能api測試,這里模擬了各種各樣的下載環(huán)境,實(shí)現(xiàn)了各種網(wǎng)絡(luò)情況下的功能單元測試;

5. ThreadingTest 主要針對頻繁開下載服務(wù)的特殊情況進(jìn)行測試;

6. HelpersTest 則是比較獨(dú)立的測試,測試/module/DownloadSystem 中Util包??Helpers 工具類中的方法;

好。最后我們回到剛開始的那幾個(gè)問題。通過類圖解析和代碼走讀大概就能得到答案。

其一,android junit框架提供了對android service的測試支持,上面的所有測試類都是基于ServiceTestCase 實(shí)現(xiàn)的;

其二,可以找到各種mock工具來模擬各種依賴于硬件、網(wǎng)絡(luò)的接口實(shí)現(xiàn),下載測試中使用的就是 mockwebserver.jar,來模擬服務(wù)器、響應(yīng);

其三,測試代碼也需要偽造相關(guān)的環(huán)境,context、resolver,包括功能源碼將系統(tǒng)相關(guān)的信息抽象成接口,在測試的過程中測試代碼可以實(shí)現(xiàn)測試所需要的fake版本,不得不說這就是代碼可測試性良好的一個(gè)體現(xiàn),目的就是繞開或模擬任何不可預(yù)期的依賴,來針對測試目標(biāo)代碼完成對邏輯的測試;

其四,對于各種網(wǎng)絡(luò)環(huán)境的測試,實(shí)際上是通過模擬不同的服務(wù)器響應(yīng)來實(shí)現(xiàn)的,絕大部分用例都是圍繞這個(gè)思路來編寫的。不過是否能覆蓋到所有情況的下載還是未知數(shù);

其五,針對一個(gè)復(fù)雜的功能系統(tǒng)來測試,整個(gè)測試代碼的架構(gòu)顯然是需要提前設(shè)計(jì)的。庖丁解牛一般,一步一步把所有的環(huán)境都模擬好,再動(dòng)手編寫各個(gè)細(xì)節(jié)點(diǎn)的測試用例。當(dāng)然,這與被測試的功能源碼的結(jié)構(gòu)設(shè)計(jì)、可測試性的考慮也是有關(guān)系的。這就是傳說中的設(shè)計(jì)吧,路漫漫其修遠(yuǎn)兮啊。

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

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

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