2013-11-27 32 views
1

測試NSDateFormatter方法的最佳做法是什麼?例如,可以說我有一個方法:使用NSDateFormatter避免易碎的單元測試

- (NSString *)formatStringFromDate:(NSDate *)date { 
    NSDateFormatter *f = [[NSDateFormatter alloc] init]; 
    [f setTimeStyle:NSDateFormatterShortStyle]; 
    [f setDateStyle:NSDateFormatterNoStyle]; 

    return [f stringFromDate:date]; 
} 

有兩種方法我能想到的測試使用獼猴桃這種方法:

1)創建單元測試相同的格式:

it(@"should format a date", ^{ 
    NSDate *date = [NSDate date]; 
    NSDateFormatter *f = [[NSDateFormatter alloc] init]; 
    [f setTimeStyle:NSDateFormatterShortStyle]; 
    [f setDateStyle:NSDateFormatterNoStyle]; 

    [[[testObject formatStringFromDate:date] should] equal:[f stringFromDate:date]]; 
}); 

2)明確寫出預期輸出:

it(@"should format a date", ^{ 
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:1385546122]; 
    NSDateFormatter *f = [[NSDateFormatter alloc] init]; 
    [f setTimeStyle:NSDateFormatterShortStyle]; 
    [f setDateStyle:NSDateFormatterNoStyle]; 

    [[[testObject formatStringFromDate:date] should] equal:@"9:55 am"]; 
}); 

現在,對我來說,#1似乎有點多餘。我知道測試會通過,因爲我基本上在單元測試中複製了該方法。

方法#2是一個非起動器,因爲它是令人難以置信的脆弱。它完全依賴於測試設備的當前區域設置,正如你期望的那樣。

所以我的問題是:是否有一個更合適的方法來測試這種方法,或者我應該繼續使用測試方法#1。

+1

測試的目的是什麼?檢查NSDateFormatter是否工作? –

+0

我實際上正在測試一個'UITableViewCell'具有'detailTextLabel.text'設置日期屬性時。我簡化了我的問題的測試和方法。 – squarefrog

+0

你想測試的代碼在哪裏?在視圖控制器或在表視圖單元格子類? – e1985

回答

1

正如您在您的評論中所說的,您要測試的是在出現日期時,單元格的detailTextLabel文本被設置爲預期格式的日期。

這可以通過幾種不同的方式進行測試,我在這裏公開了一個我會去的。

首先,每次我們想格式化一個日期時創建一個日期格式化器效率不高,這使得測試更加困難。

所以我的建議是在你的表視圖控制器創建的日期格式屬性:

// .h 
@property (strong, nonatomic) NSDateFormatter *dateFormatter; 

// .m 
- (NSDateFormatter *) dateFormatter 
{ 
    if (_dateFormatter == nil) 
    { 
     _dateFormatter = [[NSDateFormatter alloc] init]; 
     [_dateFormatter setTimeStyle:NSDateFormatterShortStyle]; 
     [_dateFormatter setDateStyle:NSDateFormatterNoStyle]; 

    } 
    return _dateFormatter; 
} 

對於日期格式我會創建一個簡單測試,驗證timeStyle和DATESTYLE。我不熟悉獼猴桃所以我用的OCUnit斷言:

TableViewController *sut;// Instantiate the table view controller 
STAssertTrue(sut.dateFormatter.timeStyle == NSDateFormatterShortStyle, nil); 
STAssertTrue(sut.dateFormatter.dateStyle == setDateStyle:NSDateFormatterNoStyle, nil); 

有此之後,這個想法是創建一個測試,驗證通過tableView:cellForRowAtIndexPath:返回的單元有detailTextLabel的文字與格式返回的字符串設定。正如你所說的測試日期格式化程序返回的字符串是脆弱的,所以我們可以嘲笑它,存根stringFromDate:返回一個常量,並驗證detailTextLabel的文本設置爲該常量。

所以我們寫測試。我會嘗試將其與獼猴桃嘲笑寫,很抱歉,如果我做錯事 - 這個想法是最重要的事情:

TableViewController *sut;// Instantiate the table view controller 

id mockDateFormatter = [NSDateFormatter mock]; 

NSString * const kFormattedDate = @"formattedDate"; 
NSDate * const date = [NSDate date]; 

[mockDateFormatter stub:@selector(stringFromDate:) andReturn:kFormattedDate withArguments:date,nil]; 

sut.dateFormatter = mockDateFormatter; 
sut.dates = @[date];// As an example we have an array of dates to show. In the real case we would have an array of the objects you want to show in the table view. 

[sut view];// In case we have the registered cells... 
UITableViewCell *cell = [sut tableView:sut.tableView 
       cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; 

STAssertEqualObjects(cell.detailTextLabel.text, kFormattedDate, nil); 

,並滿足該測試將是這樣的方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // I assume you have a standard cell registered in your table view 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"]; 

    NSDate *date = [self.dates objectAtIndex:indexPath.row]; 
    cell.detailTextLabel.text = [self.dateFormatter stringFromDate:date]; 

    return cell; 
} 

希望它有幫助。

+0

優秀的答案,正是我在找的東西。謝謝。 – squarefrog

+1

只是一個小提示:我會使用'STAssertEquals(sut.dateFormatter.timeStyle,NSDateFormatterShortStyle,nil)'。失敗時,錯誤消息顯示當前將什麼'timeStyle'分配給日期格式化程序,因此有更多信息。 –

相關問題