其實(shí)單元測(cè)試不僅能保證項(xiàng)目進(jìn)度還能優(yōu)化你的設(shè)計(jì)。有些開發(fā)者會(huì)說,寫單元測(cè)試代碼太費(fèi)勁了,比寫業(yè)務(wù)代碼還麻煩??墒侨绻麖?qiáng)迫開發(fā)者必須寫單元測(cè)試代碼的時(shí)候。聰明且又想‘偷懶’的開發(fā)人員為了將來可以更方便地編寫測(cè)試代碼。唯一的辦法就是通過優(yōu)化設(shè)計(jì),盡可能得將業(yè)務(wù)代碼設(shè)計(jì)成更容易測(cè)試的代碼。慢慢地開發(fā)者就會(huì)發(fā)現(xiàn)。自己設(shè)計(jì)的程序耦合度也越來越低。每個(gè)單元程序的輸入輸出,業(yè)務(wù)內(nèi)容和異常情況都會(huì)盡可能變得簡(jiǎn)單。最后發(fā)現(xiàn)自己的編程習(xí)慣和設(shè)計(jì)能力也越來越老練了。
創(chuàng)新互聯(lián)建站堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的嵐皋網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
其實(shí)容易測(cè)試的代碼基本上可以和設(shè)計(jì)良好的代碼劃等號(hào)。因?yàn)橐粋€(gè)單元測(cè)試用例其實(shí)就是一個(gè)單元的最早用戶。容易使用顯然意味著良好的設(shè)計(jì)。
有著良好設(shè)計(jì)的項(xiàng)目一直是很注重代碼重用的。代碼重用的好處在這里就不多說了。但是要做到代碼重用首先要保證被重用的單元程序必須是個(gè)非常優(yōu)秀的程序,除了良好的設(shè)計(jì),還要有詳細(xì)的文檔。另外最重要的其實(shí)是單元測(cè)試代碼。不知道大家有沒有這樣的經(jīng)歷?當(dāng)大家不清楚一個(gè)API 函數(shù)如何使用而去尋找文檔的幫助時(shí),往往會(huì)跳過大段的英文說明而去直接看文檔中提供的樣例程序,然后在自己的程序中依葫蘆畫瓢調(diào)用這個(gè)函數(shù)。那么,您有沒有意識(shí)到,被重用的代碼如果有了單元測(cè)試代碼。你的測(cè)試代碼就可以成為這個(gè)函數(shù)最好的API 了。
單元測(cè)試代碼還可以通過簡(jiǎn)單的事務(wù)回滾功能在生產(chǎn)環(huán)境上做基于真實(shí)數(shù)據(jù)的測(cè)試而不用擔(dān)心會(huì)產(chǎn)生不必要的數(shù)據(jù)。利用這樣的測(cè)試代碼我們可以在發(fā)布程序后check 剛才的發(fā)布是否成功。以往發(fā)布的時(shí)候我們經(jīng)常會(huì)碰到一種比較尷尬的情況,當(dāng)我們將程序發(fā)布到正式環(huán)境上后,我們每個(gè)人心里一直還是有點(diǎn)后顧之憂。因?yàn)槲覀儾荒茉谡江h(huán)境上運(yùn)行我們的程序,只能被動(dòng)地等待客戶操作過后才知道發(fā)布的程序是否正常。這種情況讓我們非常被動(dòng),如果運(yùn)氣好可能不出什么問題,可是一旦客戶在正式環(huán)境上發(fā)現(xiàn)報(bào)了個(gè)系統(tǒng)異常之類的錯(cuò)誤或者出現(xiàn)錯(cuò)誤數(shù)據(jù),那就后果很嚴(yán)重了,這將影響到產(chǎn)品的聲譽(yù),顯然這樣也是很沒面子事。如果我們運(yùn)行過單元測(cè)試代碼,萬一有問題我們就可以主動(dòng)的發(fā)現(xiàn)并且修改后重新發(fā)布。
單元測(cè)試是參與項(xiàng)目開發(fā)的工程師在項(xiàng)目代碼之外建立的白盒測(cè)試工程,用于執(zhí)行項(xiàng)目中的目標(biāo)函數(shù)并驗(yàn)證其狀態(tài)或者結(jié)果,其中,單元指的是測(cè)試的最小模塊,通常指函數(shù)。如圖1所示的綠色文件夾即是單元測(cè)試工程。這些代碼能夠檢測(cè)目標(biāo)代碼的正確性,打包時(shí)單元測(cè)試的代碼不會(huì)被編譯進(jìn)入APK中。
處于高速迭代開發(fā)中的Android項(xiàng)目往往需要除黑盒測(cè)試外更加可靠的質(zhì)量保障,這正是單元測(cè)試的用武之地。單元測(cè)試周期性對(duì)項(xiàng)目進(jìn)行函數(shù)級(jí)別的測(cè)試,在良好的覆蓋率下,能夠持續(xù)維護(hù)代碼邏輯,從而支持項(xiàng)目從容應(yīng)對(duì)快速的版本更新。
單元測(cè)試(unit testing),是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證。對(duì)于單元測(cè)試中單元的含義,一般來說,要根據(jù)實(shí)際情況去判定其具體含義,如C語言中單元指一個(gè)函數(shù),Java里單元指一個(gè)類,圖形化的軟件中可以指一個(gè)窗口或一個(gè)菜單等。總的來說,單元就是人為規(guī)定的最小的被測(cè)功能模塊。單元測(cè)試是在軟件開發(fā)過程中要進(jìn)行的最低級(jí)別的測(cè)試活動(dòng),軟件的獨(dú)立單元將在與程序的其他部分相隔離的情況下進(jìn)行測(cè)試。 在一種傳統(tǒng)的結(jié)構(gòu)化編程語言中,比如C,要進(jìn)行測(cè)試的單元一般是函數(shù)或子過程。在像C++這樣的面向?qū)ο蟮恼Z言中, 要進(jìn)行測(cè)試[1] 的基本單元是類。對(duì)Ada語言來說,開發(fā)人員可以選擇是在獨(dú)立的過程和函數(shù),還是在Ada包的級(jí)別上進(jìn)行單元測(cè)試。單元測(cè)試的原則同樣被擴(kuò)展到第四代語言(4GL)的開發(fā)中,在這里基本單元被典型地劃分為一個(gè)菜單或顯示界面。 經(jīng)常與單元測(cè)試聯(lián)系起來的另外一些開發(fā)活動(dòng)包括代碼走讀(Code review)
首先我們需要先下載相應(yīng)的 JUnit 相關(guān)的 JAR 包,下載的過程可以去 JUnit 的官方網(wǎng)站,也可以直接通過 Maven 資源倉庫來完成。
使用簡(jiǎn)單的 @Test 注解實(shí)現(xiàn)我們的測(cè)試方法的編寫和執(zhí)行
準(zhǔn)備工作做好之后,接下來我們就可以開始嘗試編寫壹個(gè)簡(jiǎn)單的測(cè)試代碼了。首先,我們編寫了壹個(gè) Calculator 類,并提供五個(gè)方法分別完成加減乘除以及求平方的運(yùn)算。代碼如下:
package net.oschina.bairrfhoinn.main;
public class Calculator {
public void add(int n){
result += n;
}
public void substract(int n){
result -= n;
}
public void multiply(int n){
result *= n;
}
public void divide(int n){
result /= n;
}
public void square(int n){
result = n * n;
}
public int getReuslt(){
return result;
}
public void clear(){
result = 0;
}
private static int result;
}
在Android Studio中可以進(jìn)行單元測(cè)試
很多的文章指導(dǎo)你應(yīng)該在“build.gradle” 文件里面添加幾行代碼從而允許單元測(cè)試,并且告訴你應(yīng)該在項(xiàng)目依賴中添加Android測(cè)試庫。
其實(shí)你并不需要按照這種錯(cuò)誤的方式去做,因?yàn)檫@是完全沒有必要的。
Android Studio本身就支持Android單元測(cè)試,你只需要在你的項(xiàng)目中配置一下就可以了。
注意:還有好幾種廣受歡迎的Android單元測(cè)試框架,比如Robolectric,它們比我在這里提到的需要更多的配置,我希望在未來可以以這個(gè)題目再寫一些指導(dǎo)文章。
創(chuàng)建你的單元測(cè)試文件夾
我喜歡把單元測(cè)試放在我的主項(xiàng)目里面,比如“com.mypath.tests.” ,你可以把測(cè)試目錄放到你想要的地方。開始之前,像下面這樣,先創(chuàng)建你的測(cè)試文件夾。(譯者注:這一步不是必須的,你也可以把單元測(cè)試類創(chuàng)建在與Android Studio默認(rèn)的ApplicationTest類相同的路徑下面)
接下來,創(chuàng)建一個(gè)叫做 “ExampleTest”的類,注意要繼承自InstrumentationTestCase類
然后可以添加一個(gè)簡(jiǎn)單的測(cè)試代碼,我們知道這段代碼肯定會(huì)運(yùn)行失敗
public class ExampleTest extends InstrumentationTestCase {
public void test() throws Exception {
final int expected = 1;
final int reality = 5;
assertEquals(expected, reality);
}
}1234567
注意:所有的測(cè)試方法必須以”test”開頭,這樣Android Studio才能自動(dòng)的找到所有你想要進(jìn)行單元測(cè)試的方法。
為你的項(xiàng)目配置單元測(cè)試
現(xiàn)在我們已經(jīng)有了一個(gè)會(huì)運(yùn)行失敗的測(cè)試單元,我們必須把它run起來。
首先點(diǎn)擊”Run- Edit Configurations”
然后點(diǎn)擊“+”從左邊彈出的列表里,選擇添加一個(gè) Android Tests,然后你可以在右上角給它改名為你想要的名字。
然后就會(huì)創(chuàng)建一下像下面這樣的測(cè)試項(xiàng)目配置
從下拉菜單中選擇你當(dāng)前的module
接下來,選擇”All in Package”選項(xiàng),然后把你的剛才創(chuàng)建的測(cè)試文件夾選中。你也可以選擇“All in Module”選項(xiàng),這樣Android Studio會(huì)自動(dòng)的找到你整個(gè)Module中的所有測(cè)試單元,你也可以通過另外的選項(xiàng),指定某一個(gè)類甚至是測(cè)試方法。
做完這一切之后,看起來應(yīng)該像下面這樣
我也喜歡選中下面的“Show chooser dialog”,這樣當(dāng)每次運(yùn)行的時(shí)候,我可以指定如何去運(yùn)行
現(xiàn)在點(diǎn)擊”Apply”然后關(guān)閉,你現(xiàn)在應(yīng)該可以看到你的測(cè)試案例已經(jīng)作為一個(gè)可以運(yùn)行的項(xiàng)目配置在Android Studio上面的工具欄上了
運(yùn)行我們的單元測(cè)試
我使用Genymotion來完成所有的事情,所以開啟你的Genymotion然后運(yùn)行test
在assertion這一行添加一個(gè)斷點(diǎn),然后點(diǎn)擊 “run debug mode”,目的是為了證明Android Studio確實(shí)執(zhí)行了我們的單元測(cè)試。
當(dāng)你開始你的測(cè)試工程之后,你會(huì)看到一個(gè)叫做“Running Tests…”的顯示窗口
當(dāng)你的測(cè)試沒有通過,點(diǎn)擊“Logcat”然后查看綜合的輸出結(jié)果,看下我們測(cè)試失敗的原因
通過控制臺(tái),你會(huì)發(fā)現(xiàn)給出的錯(cuò)誤理由應(yīng)該是
“junit.framework.AssertionFailedError: expected:1 but was:5”1