2013-11-27 3 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', когда присутствует свойство date. Я упростил тест и метод для моего вопроса. – 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 в наборе со строкой, возвращаемой форматером , Как вы сказали, тестирование строки, возвращаемой форматированием даты, является хрупкой, поэтому мы можем издеваться над этим, stub 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» в настоящее время назначено для форматирования даты, и поэтому является более информативным. –

Смежные вопросы