HC_assertThat(queryUrl.absoluteString, HC_containsString(@"p1=v1"));
HC_assertThat(queryUrl.absoluteString, HC_containsString(@"p2=v2"));
}
代碼6,URL參數測試用例
匹配規則中的陷阱
由于匹配規則的粒度較細,所以對于某些運行結果需要考慮到多種情況,否則正常的結果也可能會斷言失敗。
例如測試用例期望得到一個空容器(例如:NSArray),而SDK則認為這個容器已經沒有存在的必要而釋放了他,返回的是一個nil。對removeAllSubviews的測試中,對一個view調用removeAllSubviews方法,期望view.subviews為空。在SDK 6.x甚至SDK 7 DP1之前,都是沒問題的,但在SDK 7 DP3中,SDK會把所有清空的容器和對象釋放,以回收系統資源。在這種條件下view.subviews返回的就是nil,如果只是做類似HC_empty()這樣的匹配,斷言會失敗,所以在斷言之前做一個subviews屬性的空判斷(代碼7)。
(void)testRemoveAllSubviews
{
UIView *subViewA = [[UIView alloc] init];
UIView *subViewB = [[UIView alloc] init];
[self.view addSubview:subViewA];
[self.view addSubview:subViewB];
HC_assertThat(self.view.subviews, HC_containsInAnyOrder(subViewA, subViewB, nil));
[self.view removeAllSubviews];
if (nil != self.view.subviews) {
HC_assertThat(self.view.subviews, HC_empty());
}
}
代碼7,removeAllSubviews用例
另外,在默認匹配規則中會有一些容易產生歧義的命名,以collection的containsInAnyOrder為例:匹配對象是一個collection對象(也就是遵循NSFastEnumeration協議的對象,NSArray等),給出若干個匹配規則或元素。期待這個規則匹配該對象是否包含給出的若干元素,且不關心順序。但在實際測試過程中會發現,這個規則要求給出的元素必須是該collection對象的完備集,也就是說要求給出的元素列表和要匹配的容器對象中的元素必須是相等的結合,但允許不關注順序。
對UMNavigationController的測試中,需要判斷增加一項URL Mapping是否生效,如果使用該匹配規則,就不能單純判斷config是否包含增量的URL,要斷言成功必須連同此前config屬性初始化寫入的值一起考慮,使用一個完整的元素集合進行匹配(代碼8)。
(void)testAddConfig
{
[UMNavigationController setViewControllerName:@"ViewControllerA" forURL:@"
um://viewa2"];
NSMutableDictionary *config = [UMNavigationController config];
NSLog(@"%@", [config allKeys]);
HC_assertThat([config allKeys],
HC_containsInAnyOrder(HC_equalTo(@"um://viewa2"), HC_equalTo(@"
um://viewa"),
HC_equalTo(@"um://viewb"), nil));
GHAssertEqualStrings(config[@"um://viewa2"], @"ViewControllerA",
@"config set error.");
}
代碼8,AddConfig用例
自建匹配規則
上述例子表明匹配規則往往無法恰好滿足測試需求,需要對默認規則進行升級。
升級一個匹配規則,首先閱讀OCHamcrest默認規則源碼,找到無法滿足需求的代碼。上述HC_containsInAnyOrder的例子中,個性需求是某個collection是否包含某幾個元素(而非完整集合),而默認規則只能匹配完整集合。閱讀源碼(代碼9)可以發現,在maches:describingMismatchTo:函數中,對規則對象的collection屬性(要進行匹配的容器對象)進行遍歷,并逐個調用matches:方法。matches:方法中針對每個collection屬性中的元素遍歷匹配規則集合(matchers),并從規則集合(matchers)中移除匹配成功的規則。當給出的規則集合(matchers)全部成功匹配過之后,matchers屬性已經為空。若此時對collection屬性的遍歷繼續進行,matches:方法就不會進入匹配邏輯,直接跳出循環返回NO,導致匹配失敗。
(BOOL)matches:(id)item
{
NSUInteger index = 0;
for (id matcher in matchers)
{
if ([matcher matches:item])
{
[matchers removeObjectAtIndex:index];
return YES;
}
++index;
}
[[mismatchDescription appendText:@"not matched: "] appendDescriptionOf:item];
return NO;
}
- (BOOL)matches:(id)collection describingMismatchTo:(id)
mismatchDescription
{
if (![collection conformsToProtocol:@protocol(NSFastEnumeration)])
{
[super describeMismatchOf:collection to:mismatchDescription];
return NO;
}
HCMatchingInAnyOrder *matchSequence =
[[HCMatchingInAnyOrder alloc] initWithMatchers:matchers
mismatchDescription:mismatchDescription];
原文轉自:http://blog.segmentfault.com/gaosboy/1190000000270521