標籤:
Unit Testing: 單元測試
測試這個詞很容易理解,那麼什麼是單元(Unit)呢?一個單元指的就是應用程式中可以測試的最小單元。一組原始碼可以測試,一般要求有明確的輸入與輸出。因此一般來說原始碼中明確的包含輸入輸出的每一個方法被認為一個測試的單元(一個case)。注意,這裡的輸出並不局限於方法的傳回值對輸入參數的改變,也包括方法在執行過程中改變的任何資料。
單元測試在程式裡面可以理解一個模組一個方法,在每個可能存在的模組都進行測試,確保每個模組都沒有問題,從而提高整體程式的品質。
單元測試的目的
單元測試的目的是將程式中所有的原始碼,隔離成最小的可測試單元,以確保每個單元的正確性,如果每個單元都能保證正確,就能保證應用程式整體相當程度的正確性。另一方面測試指令碼本身就是被測試代碼的實際使用代碼,這對於開發人員理解被測試單元的使用是用協助的。
測試是分黑箱測試和白盒測試(概念此處不在解釋),單元測試其實就是一種白盒測試,開發人員對現有已經實現的模組自己寫對應測試指令碼進行測試,這中間還包含測試案例的設計。相對來說還是由開發人員自己來完成白盒測試,然後在交由測試團隊進行黑箱測試,這樣也更加有助於提升測試流程的完整性,最終提高產品的品質。
單元測試的內容:
- 單元測試的測試目的
- 模組介面測試
- 局部資料結構測試
- 路徑測試
- 錯誤處理測試
- 邊界測試
在現有的開發工作中,我們一般都會忽略掉單元測試的重要性,功能開發完成以後開發人員拿到現有的測試案例,直接針對每條用例進行手工的測試,測試通過就進行提測,之後測試人員還是重複手工測試的流程、資料的mock、專項測試等,這樣以來白盒測試的流程有時間份量會變的很低,開發人員不知道自己模組代碼的覆蓋路問題,更多的時間可能某些代碼一直到到上線都從來沒有跑過,以至於到了真實環境下會產生一些意想不到的問題,這樣以來風險極高,整體來說單元測試還是至關重要的。
具體的怎麼在Xcode上建立或者添加使用單元測試請閱讀本文末尾的風之痕連結。
言歸正傳,本文主要講 單元測試之NSNull 檢測,在現實開發中,我們最煩的往往就是服務端返回的資料中隱藏著NSNull的資料,一般我們的做法是通過
[data isKindOfClass:[NSNull class]] 對資料先做一層判斷然後為空白的情況下付給 Null 字元串或者一些其他的初始變數。但是,業務資料層的代碼本來就比較繁雜,還要我加上這個多餘的判斷來添堵?門都沒有!那麼我們的單元測試就派上用處了。
我們用一個帶空資料的介面來走一遍流程。
資料大概是這樣子的,其中data 下的 isLike欄位的值是NSNull 狀態
1.在test檔案中建立一個test
- (void)testGetNoticeListWithExerciseType{ //此處換成你自己的介面 [NetManager getNoticeListWithExerciseType:@"" keyword:@"" pageSize:@"" pageNum:@"" whenSuccess:^(NSDictionary *responseDic) { //資料非空 XCTAssertNotNil(responseDic, @"返回出錯"); //返回碼為0的情況下是正確的 (這個你們的有可能不是) XCTAssertTrue([[responseDic objectForKey:@"code"] isEqualToNumber:@(0)],@"code 必須是@(0)"); //判斷資料的所有層是否都為非空(可以返回一個免檢欄位的key數組,允許數組中的欄位為空白 ) [self judgeNilData:[responseDic objectForKey:@"data"] andKey:@"" finished:^NSArray *{ return @[@"isLike",@"like_count"]; }]; //判斷資料的所有層是否都為非空(必須所有欄位都未非空才能通過測試) //[self judgeNullData:[responseDic objectForKey:@"data"] andKey:nil exemptionKeys:nil]; NOTIFY //繼續執行 } andFailed:^(NSString *errorDesc) { NOTIFY //繼續執行 }]; //等待 WAIT}
2.核心代碼(粘貼到該test檔案下)
/** * 覆蓋檢測資料中是否含有NSNull 資料 * 日常中一般情況的下的閃退大多都是資料的空導致的,事先檢測出是否包含空的資料能大大提升程式的穩定性 * * @param data 字典或者數組資料 (一般由json轉化而來) * @param key data 的 key (多層資料情況下直接置nil即可) * @param keys 免檢欄位 (在這裡 返回你運行為空白的欄位名稱的key數組) */- (void)judgeNullData:(nullable id)data andKey:(nullable NSString *)key exemptionKeys:( NSArray * (^)(void))keys{ //字典 if ([data isKindOfClass:[NSDictionary class]]) { for (id obj in ((NSDictionary *)data).allKeys) { //遞迴遍曆字典 [self judgeNullData:[((NSDictionary *)data) objectForKey:obj] andKey:obj exemptionKeys:keys]; } } //數組 else if ([data isKindOfClass:[NSArray class]]) { for (id obj in data) { //遞迴遍曆數組 [self judgeNullData:obj andKey:nil exemptionKeys:keys]; } } //除字典和數組外(進行非空判斷) else{ //添加免檢欄位(允許array數組中的欄位為NSNull) if (keys) { NSArray *array = keys(); if ([array containsObject:key]) { return; } } //斷言檢測欄位非空 //檢測nil XCTAssertNotNil(data); //這個斷言不能判斷 NSNull 只能判斷nil //檢測NSNull XCTAssertFalse([data isKindOfClass:[NSNull class]],@"欄位為空白"); //, @"欄位為空白" //列印輸出空的欄位 if ([data isKindOfClass:[NSNull class]]) { if (!(key == nil)) { NSLog(@"key:%@ 對應的值為NSNull",key); } } if (data == nil) { NSLog(@"數組為空白"); } return; }}
3.如,點擊左上方的開始測試
4.最後測試會報錯,如下
以上簡介部分文字摘自 文/風之痕_(簡書作者)
原文連結:http://www.jianshu.com/p/f4ba532caed0
單元測試之NSNull 檢測