URLManager是一個基于UINavigationController和UIViewController,以URL Scheme為設計基礎的導航控件,目的是實現ViewController的松耦合,不依賴。
準備框架,定義基類
首先按照之前的兩篇文章介紹的方法導入單元測試框架和匹配引擎框架,建立好測試Target,并配置編譯選項。
定義測試用例基類:UMTestCase(代碼1),其他用例全部繼承自UMTestCase。
#import @interface UMTestCase : GHTestCase @end
代碼1,UMTestCase,用例基類
構建用例
URLManager工具類(UMTools)測試用例(UMToolsTestCase)。UMTools中擴展了NSURL,NSString和UIView,方法涉及到給URL添加QueryString和從QueryString中讀取參數,對字符串做子串判斷,進行URL的編碼和解碼,對UIView的x,y,width和height的直接讀寫等。需要在用例中定義測試過程中會使用到屬性(代碼2), 并在setUpClass中初始化他們(代碼3)。
代碼2,定義屬性
// 普通字符串,帶有字母和數字
@property (strong, nonatomic) NSString *string;
// 普通字符串,僅帶有字母
@property (strong, nonatomic) NSString *stringWithoutNumber;
// 將被做URLEncode的字符串,含有特殊字符和漢字
@property (strong, nonatomic) NSString *toBeEncode;
// 把 toBeEncode 編碼后的串
@property (strong, nonatomic) NSString *encoded;
// 普通的URL,帶有QueryString
@property (strong, nonatomic) NSURL *url;
// 去掉上邊一個URL的QueryString
@property (strong, nonatomic) NSURL *noQueryUrl;
// 一個普通的UIView
@property (strong, nonatomic) UIView *view;
(void)setUpClass
{
self.string = @"NSString For Test with a number 8848.";
self.stringWithoutNumber = @"NSString For Test.";
self.toBeEncode = @"~!@#$%^&*()_+=-[]{}:;\"'<>.,/?123qwe漢字";
self.encoded = @"%7E%21%40%23%24%25%5E%26%2A%28%29_%2B%3D-%5B%5D%
7B%7D%3A%3B%22%27%3C%3E.%2C%2F%3F123qwe%E6%B1%89%E5%AD%97";
self.url = [NSURL URLWithString:@"http://example.com
/patha/pathb/?p2=v2&p1=v1"];
self.noQueryUrl = [NSURL URLWithString:@"http://example.com
/patha/pathb/"];
self.view = [[UIView alloc] initWithFrame:CGRectMake(10.0f,
10.0f, 100.0f, 100.f)];
}
代碼3,初始化屬性
使用單元測試框架中的斷言處理簡單用例
單元測試是白盒測試,要做到路徑覆蓋(代碼4)。 對“ContainsString”的測試進行正向和反向兩種情況(即YES和NO兩種返回結果)。
#pragma mark - UMString
- (void)testUMStringContainsString
{
NSString *p = @"For";
NSString *np = @"BAD";
GHAssertTrue([self.string containsString:p],
@"\"%@\" should contains \"%@\".",
self.string, p);
GHAssertFalse([self.string containsString:np],
@"\"%@\" should not contain \"%@\".",
self.string, p);
代碼4,字符串測試用例
同時單元測試又要對功能負責,因此在路徑覆蓋之外還要盡量照顧到完整的功能。例如,對URLEncode的測試(代碼5),要對盡量全面的特殊字符進行測試,而不是從源碼實現中取出枚舉的字符。
(void)testUrlencode
{
GHAssertEqualStrings([self.toBeEncode urlencode], self.encoded,
@"URLEncode Error.",
self.toBeEncode, self.encoded);
GHAssertEqualStrings([self.encoded urldecode], self.toBeEncode,
@"URLDecode Error.",
self.encoded, self.toBeEncode);
}
代碼5,URLEncode測試用例
在進行這個測試之前,urlencode的實現忽視了對“~”的編碼,正是由于單元測試用例所取的特殊字符是單獨列舉,并非從實現枚舉中獲取,檢查出了這個錯誤。
引入匹配引擎,使用匹配引擎默認規則
前文提到過匹配引擎可以使測試用例中的斷言更加豐富,URLManager的用例中也使用了匹配引擎:OCHamcrest。
在此前的介紹中提到,引入OCHamcrest可以通過定義 HC_SHORTHAND 來開啟匹配引擎的簡寫模式。因為開啟簡寫模式后匹配規則中的“containsString”規則和上述例子(代碼5)中的“containsString:”方法命名沖突,導致測試程序無法正常運行,所以這個工程直接使用了類似 HC_asserTaht 這樣帶有HC前綴的完整命名。
我建議使用匹配引擎的開發者謹慎開啟簡寫功能,OCHamcrest的匹配規則簡寫通常是很常見的單詞,非常容易與工程中的類定義或方法定義重名。即使當下沒有規則和方法名發生沖突,隨著工程代碼量的增加,一旦出現命名沖突的情況,重構的成本將非常高。
匹配引擎可以提供更豐富的斷言,最簡單的例如,URLManager的UMURL擴展支持向一個URL上添加參數,對這個方法測試斷言就用到了匹配某個字符串是否包含某子串的規則(代碼6)。
#pragma mark - UMURL
- (void)testAddParams
{
NSURL *queryUrl = [self.noQueryUrl addParams:@{@"p1":@"v1",@"p2":@"v2"}];
原文轉自:http://blog.segmentfault.com/gaosboy/1190000000270521