既然認為它是好的,就要發揮到極限-系列之二單元測試
既然測試是好的,那就把它發揮到極限。
測試是好的,這一點無可厚非,幾乎做軟件的人都是認可的,本篇只是談談測試中的單元測試部分,單元測試的目的是為了保證類中的方法是符合設計時的需求的,需求驅動似的類實現,^_^
單元測試的好處
1、保證類對于設計以及需求的符合
在沒有單元測試的情況下,其實是很難保證類對于設計以及需求的符合的,很多情況往往會因為開發人員本身的因素將實現代碼復雜化,并且編寫出很多設計和需求根本不需要的東西。
2、降低調試的復雜性
想想在沒有單元測試的情況下,調試通常是集成時才做的,這個時候要通過慢慢的跟蹤來查找問題的原因,而在web系統中就更痛苦了,總是要重啟,如果不想那么痛苦,就采用單元測試吧。
3、減少集成時出錯的機率
單元測試可保證暴露給外部的API的正確性,減少要通過集成才發現錯誤的現象。
4、保證重構和簡單設計的可行
想想,如果沒有單元測試,怎么敢對代碼做重構呢,如果沒有單元測試,簡單設計很難通過重構去演變成為將來更好的設計。
單元測試的實現
單元測試的實現采取的方法通常是xUnit,在Java界就是junit了,最重要的仍然不是工具,而是怎么去實現單元測試的方法,測試驅動開發無疑是最佳的編寫測試的方法,首先根據設計或需求編寫測試,根據測試編寫代碼,直到測試通過為止。
在代碼出現bug時,一定要先把出現bug的情況補充到測試中去,接下來仍然是修改實現代碼,直到測試通過。
單元測試編寫的原則其實很簡單,就是測試一定情況下類的執行是否符合預期。
還是舉例來說:
假設需要編寫一個根據用戶名和密碼驗證用戶的服務,按照TDD我們首先編寫單元測試類,我們應該怎么來編寫這個單元測試類呢,一般可按照一個這樣的步驟:
1、分析類的輸入。
這點通常是分析類依賴外部什么類,需要在測試類中提前注入。
以上面的服務來說,通常需要依賴的是用戶的Dao類。
2、分析方法的輸入造成的輸出的影響。
這點通常是分析方法輸入的參數對執行結果造成的影響。
以上面的服務來說,輸入的參數為用戶名和密碼,這個時候會有幾種情況會出現:
2.1 用戶名或密碼為null
在這種情況下,假設期待的輸出為false
2.2 用戶名和密碼都為null
在這種情況下,假設期待的輸出為false
2.3 輸入的用戶名和密碼在系統中存在
在這種情況下,假設期待的輸出為true
2.4 用戶名或密碼其中一項輸入不正確,驗證不通過
在這種情況下,假設期待的拋出AuthronizedException
在經過這樣的分析后,就可以開始編寫測試類了,編寫的測試類如下(示例代碼而已):

public class UserServiceTest extends TestCase
{

private UserDao dao=null;
private UserService service=null;
private User user=null;

public static void main(String[] args)
{
junit.textui.TestRunner.run(UserServiceTest.class);
}


protected void setUp() throws Exception
{
super.setUp();
dao=new UserDaoImpl();
user=new User();
user.setName("TEST_BLUEDAVY");
user.setPass("JERRY");
dao.save(user);
service=new UserServiceImpl();
service.setDao(dao);
}


protected void tearDown() throws Exception
{
super.tearDown();
dao.delete(user);
}

public void testWhenNameAndPassAreNull()
{
assertEquals(false,service.login(user.getName(),user.getPass()));
}


public void testWhenNameOrPassIsNull()
{
assertEquals(false,service.login(user.getName(),user.getPass()));
}

public void testWhenNameAndPassAreCorrect()
{
assertEquals(true,service.login(user.getName(),user.getPass()));
}

public void testWhenNameOrPassIsError()
{

try
{
service.login(user.getName(),user.getPass());
}

catch(Exception e)
{
assertEquals(AuthronizedException.class,e.getClass());
}
}
}
在編寫完測試類后就可以開始編寫實現代碼了,實現代碼在編寫的時候很簡單,只要能夠保證測試通過就完事,在測試通過后可以開始考慮重構的事,重構仍然只要保證測試通過即可,其實這個時候就可以看到,簡單設計就變得可行了,因為可以通過重構來提升設計。
如果將來這段代碼出現bug,就把bug中的輸入情況也編寫為一個測試方法進行測試,開始運行就應該和bug一樣出現問題,這時只需去修正實現代碼,直到測試通過為止,那么bug也就自然被修正了。
簡單的單元測試的編寫較為簡單,復雜的單元測試則可能需要使用Mock來模擬一些環境,Mock方面的工具有很多,大家可以去參考相關的開源工具的網站。
經驗總結
對于單元測試通常很多人都有疑問,執行起來的時候經常是不夠徹底,特別是在項目時間緊張的情況下,總是覺得編寫測試是一種耽誤時間的事,其實編寫單元測試會為你節省非常多的時間,想想我們大部分的項目都是在集成、修改bug和維護上消耗了大量的時間,既然單元測試這么好,那么我們就實現單元測試吧。
在單元測試中最重要的注意點就是不要依賴于正常的運行數據,所有的數據都要通過代碼模擬出來,在測試完畢后清除,避免造成測試對于運行數據的依賴,同時也避免測試數據對于實際運行系統的影響。
測試是好的,這一點無可厚非,幾乎做軟件的人都是認可的,本篇只是談談測試中的單元測試部分,單元測試的目的是為了保證類中的方法是符合設計時的需求的,需求驅動似的類實現,^_^
單元測試的好處
1、保證類對于設計以及需求的符合
在沒有單元測試的情況下,其實是很難保證類對于設計以及需求的符合的,很多情況往往會因為開發人員本身的因素將實現代碼復雜化,并且編寫出很多設計和需求根本不需要的東西。
2、降低調試的復雜性
想想在沒有單元測試的情況下,調試通常是集成時才做的,這個時候要通過慢慢的跟蹤來查找問題的原因,而在web系統中就更痛苦了,總是要重啟,如果不想那么痛苦,就采用單元測試吧。
3、減少集成時出錯的機率
單元測試可保證暴露給外部的API的正確性,減少要通過集成才發現錯誤的現象。
4、保證重構和簡單設計的可行
想想,如果沒有單元測試,怎么敢對代碼做重構呢,如果沒有單元測試,簡單設計很難通過重構去演變成為將來更好的設計。
單元測試的實現
單元測試的實現采取的方法通常是xUnit,在Java界就是junit了,最重要的仍然不是工具,而是怎么去實現單元測試的方法,測試驅動開發無疑是最佳的編寫測試的方法,首先根據設計或需求編寫測試,根據測試編寫代碼,直到測試通過為止。
在代碼出現bug時,一定要先把出現bug的情況補充到測試中去,接下來仍然是修改實現代碼,直到測試通過。
單元測試編寫的原則其實很簡單,就是測試一定情況下類的執行是否符合預期。
還是舉例來說:
假設需要編寫一個根據用戶名和密碼驗證用戶的服務,按照TDD我們首先編寫單元測試類,我們應該怎么來編寫這個單元測試類呢,一般可按照一個這樣的步驟:
1、分析類的輸入。
這點通常是分析類依賴外部什么類,需要在測試類中提前注入。
以上面的服務來說,通常需要依賴的是用戶的Dao類。
2、分析方法的輸入造成的輸出的影響。
這點通常是分析方法輸入的參數對執行結果造成的影響。
以上面的服務來說,輸入的參數為用戶名和密碼,這個時候會有幾種情況會出現:
2.1 用戶名或密碼為null
在這種情況下,假設期待的輸出為false
2.2 用戶名和密碼都為null
在這種情況下,假設期待的輸出為false
2.3 輸入的用戶名和密碼在系統中存在
在這種情況下,假設期待的輸出為true
2.4 用戶名或密碼其中一項輸入不正確,驗證不通過
在這種情況下,假設期待的拋出AuthronizedException
在經過這樣的分析后,就可以開始編寫測試類了,編寫的測試類如下(示例代碼而已):






































































在編寫完測試類后就可以開始編寫實現代碼了,實現代碼在編寫的時候很簡單,只要能夠保證測試通過就完事,在測試通過后可以開始考慮重構的事,重構仍然只要保證測試通過即可,其實這個時候就可以看到,簡單設計就變得可行了,因為可以通過重構來提升設計。
如果將來這段代碼出現bug,就把bug中的輸入情況也編寫為一個測試方法進行測試,開始運行就應該和bug一樣出現問題,這時只需去修正實現代碼,直到測試通過為止,那么bug也就自然被修正了。
簡單的單元測試的編寫較為簡單,復雜的單元測試則可能需要使用Mock來模擬一些環境,Mock方面的工具有很多,大家可以去參考相關的開源工具的網站。
經驗總結
對于單元測試通常很多人都有疑問,執行起來的時候經常是不夠徹底,特別是在項目時間緊張的情況下,總是覺得編寫測試是一種耽誤時間的事,其實編寫單元測試會為你節省非常多的時間,想想我們大部分的項目都是在集成、修改bug和維護上消耗了大量的時間,既然單元測試這么好,那么我們就實現單元測試吧。
在單元測試中最重要的注意點就是不要依賴于正常的運行數據,所有的數據都要通過代碼模擬出來,在測試完畢后清除,避免造成測試對于運行數據的依賴,同時也避免測試數據對于實際運行系統的影響。
posted on 2006-01-22 23:43 BlueDavy 閱讀(1934) 評論(3) 編輯 收藏 所屬分類: Java 、軟件工程