SlideShare a Scribd company logo
RAMBLER&CO 2015
TEST-DRIVEN
DEVELOPMENT
В IOS
Содержание
1) Разработка через тестирование – что это?
2) Цикл разработки через тестирование
3) Примеры применения
4) Преимущества и недостатки
5) Литература и ссылки
Разработка через тестирование – что это?
Разработка через тестирование (Test-Driven Development) - техника
разработки программного обеспечения, которая определяет разработку
через написание тестов. В сущности вам нужно выполнять три простых
повторяющихся шага:
- Написать тест для новой функциональности, которую вы хотите добавить;
- Написать код, который пройдет тест;
- Провести рефакторинг нового и старого кода.
Мартин Фаулер
Цикл разработки через тестирование
1) Добавление теста
2) Запуск всех тестов: убедиться, что новый тест не проходят
3) Написать код
4) Запуск всех тестов: убедиться, что все тесты проходят
5) Рефакторинг
Цикл разработки через тестирование
Примеры применения
Интерфейс тестируемого метода:
- (NSArray *)sortEvents:(NSArray *)events;
Тест:
- (void)testSortEvents {
// given
id firstEvent = [self mockEventWithClass:kCinemaEventType name:@"В"];
id secondEvent = [self mockEventWithClass:kCinemaEventType name:@"Г"];
id thirdEvent = [self mockEventWithClass:kPerfomanceEventType name:@"А"];
id fourthEvent = [self mockEventWithClass:kPerfomanceEventType name:@"Б"];
NSArray *correctSortedArray = @[firstEvent, secondEvent, thirdEvent, fourthEvent];
NSArray *incorrectSortedArray = @[thirdEvent, secondEvent, fourthEvent, firstEvent];
// when
NSArray *sortedWithTestingMethodArray = [self.service sortEvents:incorrectSortedArray];
// then
XCTAssertEqualObjects(correctSortedArray, sortedWithTestingMethodArray, @"Сортировка эвентов работает
неправильно");
}
Пример 1. Сортировка событий
Примеры применения
Реализация метода:
- (NSArray *)sortEvents:(NSArray *)events {
// Сортировка событий (Сначала кино, затем остальные, обе секции по алфавиту)
NSMutableArray *cinemaEvents = [[NSMutableArray alloc] init];
NSMutableArray *otherEvents = [[NSMutableArray alloc] init];
for (Event *event in events) {
if ([event.type isEqualToString:kCinemaEventType]) {
[cinemaEvents addObject:event];
} else {
[otherEvents addObject:event];
}
}
NSComparisonResult (^sortBlock)(Event *firstEvent, Event *secondEvent) = ^NSComparisonResult(Event *firstEvent,
Event *secondEvent) {
return [firstEvent.type compare:secondEvent.type
options:NSNumericSearch];
};
[cinemaEvents sortUsingComparator:sortBlock];
[otherEvents sortUsingComparator:sortBlock];
return [cinemaEvents arrayByAddingObjectsFromArray:otherEvents];
}
Примеры применения
Как результат - инверсия ответственности в TDD
Примеры применения
Маппер должен уметь:
1) мапить объекты (неожиданно)
2) обрабатывать кривую выдачу (Null, неверный тип данных, неверная
структура выдачи)
3) обеспечивать консистентность данных (проверка обязательных полей)
Интерфейс тестируемого метода:
- (NSArray *)mapEvents:(id)responseObject;
Пример 2. Маппер
Примеры применения
Тест:
- (void)testMapEventsResponseSuccessful {
// given
NSDictionary *responseObject = @{kEventResponseKey : @[@{@"type" : @1,
@"name" : @"test",
@"description" : @"test"}]};
// when
NSArray *events = [self.mapper mapEvents:responseObject];
// then
Event *event = events[0];
[self checkObject:event
forKeyExistence:@[@"type", @"name", @"description"]];
}
- (void)checkObject:(id)object
forKeyExistence:(NSArray *)keys {
for (NSString *key in keys) {
if (![object valueForKey:key]) {
XCTFail(@"Объект не содержит необходимого поля - %@", key);
}
}
}
Примеры применения
Реализация метода:
- (NSArray *)mapEvents:(id)responseObject {
NSDictionary *mappingsDictionary = @{kEventResponseKey : [self eventResponseMapping]};
RKMappingResult *mappingResult = [self mapResponseObject:responseObject
withMappingsDictionary:mappingsDictionary];
if (mappingResult) {
return [mappingResult array];
}
return @[];
}
Примеры применения
Тест:
- (void)testMapEventsResponseWithMissingMandatoryFields {
// given
NSDictionary *responseObject = @{kEventResponseKey : @[@{@"name" : @"test"}]};
// when
NSArray *events = [self.mapper mapEvents:responseObject];
// then
XCTAssertFalse([events count]);
}
Реализация метода:
- (NSArray *)mapEvents:(id)responseObject {
NSDictionary *mappingsDictionary = @{kEventResponseKey : [self eventResponseMapping]};
RKMappingResult *mappingResult = [self mapResponseObject:responseObject
withMappingsDictionary:mappingsDictionary];
if (mappingResult) {
//Проверяем наличие обязательных полей в объекте
NSArray *events = [self checkMandatoryFields:[mappingResult array]];
return events;
}
return @[];
}
Примеры применения
Тест:
- (void)testMapEventsResponseWithNulls {
// given
NSDictionary *responseObject = @{kEventResponseKey : @[@{@"type" : @1,
@"name" : [NSNull null],
@"description" : [NSNull null]}]};
// when
NSArray *events = [self.mapper mapEvents:responseObject];
// then
Event *event = events[0];
XCTAssertNotNil(event.type, @"");
XCTAssertNil(event.name, @"");
}
- (void)testMapEventsResponseWithWrongType {
// given
NSDictionary *responseObject = @{kEventResponseKey : @[@{@"type" : @"123"}]};
// when
NSArray *events = [self.mapper mapEvents:responseObject];
// then
Event *event = events[0];
XCTAssertTrue([event.type isEqual:@123]);
}
Примеры применения
Тест:
- (void)testMapPlanResponseWithDrunkenResponseStructure {
// given
NSArray *responseObject = @[@{@"test" : @[]}, @{@"test" : @"test"}];
// when
NSArray *events = [self.mapper mapEvents:responseObject];
// then
XCTAssertFalse([events count]);
}
Преимущества и недостатки
Преимущества Недостатки
Продумывание интерфейса до
реализации
Сложность применения (безопасность
данных, UI, базы данных)
Меньше отладки Больше времени
Уверенность при изменении Ложное ощущение надежности
Меньше ошибок Ошибка в тесте
Документация тестами Поддержка тестов
Модульность
Полноценные тесты
Преимущества и недостатки
Разработка через тестирование
поощряет простой дизайн и
внушает уверенность.
TDD encourages simple designs
and inspires confidence.
Кент Бек
Литература и ссылки
Kent Beck – Test-Driven Development: By example
http://www.objc.io/issue-15/
https://en.wikipedia.org/wiki/Test-driven_development
http://qualitycoding.org/objective-c-tdd/
http://agiledata.org/essays/tdd.html#WhatIsTDD
http://www.basilv.com/psd/blog/2009/test-driven-development-benefits-limitations-and-
techniques
http://martinfowler.com/articles/is-tdd-dead/
http://habrahabr.ru/post/206828/
http://habrahabr.ru/post/216923/
http://iosunittesting.com/
Спасибо!
Rambler&Co

More Related Content

PPTX
Андрей Зайцев - TDD в кровавом энтерпрайзе
PPTX
QA Лекция2
PPTX
лекция3 QA
PPTX
лекция4 qa
PPTX
Фофанов Илья - Лучшие практики проектирования и реализации API на C#
PPTX
Unit tests final
PDF
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
PDF
Unit testing iOS Applications
Андрей Зайцев - TDD в кровавом энтерпрайзе
QA Лекция2
лекция3 QA
лекция4 qa
Фофанов Илья - Лучшие практики проектирования и реализации API на C#
Unit tests final
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
Unit testing iOS Applications

What's hot (19)

PDF
Java осень 2014 занятие 3
PPTX
Использование Mock-объектов в TDD на платформе .NET
PDF
Тестирование весна 2013 лекция 2
KEY
iPhone Unit Testing (Google tool Box)
PDF
Автоматизация UI тестирования под Windows и Windows Phone
PPTX
Как создать качественный статический анализатор
PDF
Тестирование осень 2013 лекция 4
PDF
kranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Java
PPT
Опыт тестирования API САПР платформы
PPTX
ковалев нестандатное нт
PDF
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
PPTX
Unit тесты java
PPTX
Dependency Injection на примере Unity и NInject
PDF
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестов
PPTX
Использование Mock объектов в модульном тестировании
PDF
Автоматизация функционального тестирования REST API
PDF
Java осень 2014 занятие 5
PDF
Victor Kuliamin.CSEDays
PPT
Надежда Серкова -- Автоматическая генерация Perl скриптов для тестирования си...
Java осень 2014 занятие 3
Использование Mock-объектов в TDD на платформе .NET
Тестирование весна 2013 лекция 2
iPhone Unit Testing (Google tool Box)
Автоматизация UI тестирования под Windows и Windows Phone
Как создать качественный статический анализатор
Тестирование осень 2013 лекция 4
kranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Java
Опыт тестирования API САПР платформы
ковалев нестандатное нт
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Unit тесты java
Dependency Injection на примере Unity и NInject
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Использование Mock объектов в модульном тестировании
Автоматизация функционального тестирования REST API
Java осень 2014 занятие 5
Victor Kuliamin.CSEDays
Надежда Серкова -- Автоматическая генерация Perl скриптов для тестирования си...
Ad

Viewers also liked (10)

PDF
Rambler.iOS #4: Как мы стали писать бизнес-логику
PPTX
Rambler.iOS #2: Введение в RestKit
PDF
Rambler.iOS #2: Практика применения BaaS в мобильных сервисах
PDF
Rambler.iOS #2: Адаптивная верстка iOS приложений
PDF
Rambler.iOS #1: Nimbus Kit Models
PPTX
ReactiveCocoa: делаем отзывчивое приложение (П. Руденко)
PDF
Rambler.iOS #8: Как не стать жертвой бэкендеров
PPTX
Viper - чистая архитектура iOS-приложения (И. Чирков)
PDF
Introduction to VIPER Architecture
PPTX
Тестирование iOS приложений. С чего начать?
Rambler.iOS #4: Как мы стали писать бизнес-логику
Rambler.iOS #2: Введение в RestKit
Rambler.iOS #2: Практика применения BaaS в мобильных сервисах
Rambler.iOS #2: Адаптивная верстка iOS приложений
Rambler.iOS #1: Nimbus Kit Models
ReactiveCocoa: делаем отзывчивое приложение (П. Руденко)
Rambler.iOS #8: Как не стать жертвой бэкендеров
Viper - чистая архитектура iOS-приложения (И. Чирков)
Introduction to VIPER Architecture
Тестирование iOS приложений. С чего начать?
Ad

More from RAMBLER&Co (20)

PDF
RDSDataSource: Основы LLVM
PDF
Rambler.iOS #9: Анализируй это!
PDF
Rambler.iOS #9: Нужны ли бэкенд-разработчики, когда есть Swift?
PDF
Rambler.iOS #9: Life with out of memory
PDF
RDSDataSource: Чистые тесты на Swift
PDF
RDSDataSource: OCLint
PDF
RDSDataSource: Построение UML диаграмм
PDF
RDSDataSource: App Thinning
PDF
RDSDataSource: Мастер-класс по Dip
PDF
RDSDataSource: YapDatabase
PDF
Rambler.iOS #8: Чистые unit-тесты
PDF
Rambler.iOS #8: Сервис-ориентированная архитектура
PDF
Rambler.iOS #8: Make your app extensible with JavaScriptCore
PDF
RDSDataSource: iOS Reverse Engineering for inexperienced
PDF
RDSDataSource: Автогенерация документации для SDK
PDF
RDSDataSource: Плюрализация в iOS
PDF
RDSDataSource: Promises
PDF
RDSDataSource: Flux, Redux, ReSwift
PDF
Rambler.iOS #7: Построение сложного табличного интерфейса
PDF
Rambler.iOS #7: Прием платежей по банковским картам в iOS приложении
RDSDataSource: Основы LLVM
Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Нужны ли бэкенд-разработчики, когда есть Swift?
Rambler.iOS #9: Life with out of memory
RDSDataSource: Чистые тесты на Swift
RDSDataSource: OCLint
RDSDataSource: Построение UML диаграмм
RDSDataSource: App Thinning
RDSDataSource: Мастер-класс по Dip
RDSDataSource: YapDatabase
Rambler.iOS #8: Чистые unit-тесты
Rambler.iOS #8: Сервис-ориентированная архитектура
Rambler.iOS #8: Make your app extensible with JavaScriptCore
RDSDataSource: iOS Reverse Engineering for inexperienced
RDSDataSource: Автогенерация документации для SDK
RDSDataSource: Плюрализация в iOS
RDSDataSource: Promises
RDSDataSource: Flux, Redux, ReSwift
Rambler.iOS #7: Построение сложного табличного интерфейса
Rambler.iOS #7: Прием платежей по банковским картам в iOS приложении

Rambler.iOS #3: Test-Driven Development в iOS

  • 2. Содержание 1) Разработка через тестирование – что это? 2) Цикл разработки через тестирование 3) Примеры применения 4) Преимущества и недостатки 5) Литература и ссылки
  • 3. Разработка через тестирование – что это? Разработка через тестирование (Test-Driven Development) - техника разработки программного обеспечения, которая определяет разработку через написание тестов. В сущности вам нужно выполнять три простых повторяющихся шага: - Написать тест для новой функциональности, которую вы хотите добавить; - Написать код, который пройдет тест; - Провести рефакторинг нового и старого кода. Мартин Фаулер
  • 4. Цикл разработки через тестирование 1) Добавление теста 2) Запуск всех тестов: убедиться, что новый тест не проходят 3) Написать код 4) Запуск всех тестов: убедиться, что все тесты проходят 5) Рефакторинг
  • 5. Цикл разработки через тестирование
  • 6. Примеры применения Интерфейс тестируемого метода: - (NSArray *)sortEvents:(NSArray *)events; Тест: - (void)testSortEvents { // given id firstEvent = [self mockEventWithClass:kCinemaEventType name:@"В"]; id secondEvent = [self mockEventWithClass:kCinemaEventType name:@"Г"]; id thirdEvent = [self mockEventWithClass:kPerfomanceEventType name:@"А"]; id fourthEvent = [self mockEventWithClass:kPerfomanceEventType name:@"Б"]; NSArray *correctSortedArray = @[firstEvent, secondEvent, thirdEvent, fourthEvent]; NSArray *incorrectSortedArray = @[thirdEvent, secondEvent, fourthEvent, firstEvent]; // when NSArray *sortedWithTestingMethodArray = [self.service sortEvents:incorrectSortedArray]; // then XCTAssertEqualObjects(correctSortedArray, sortedWithTestingMethodArray, @"Сортировка эвентов работает неправильно"); } Пример 1. Сортировка событий
  • 7. Примеры применения Реализация метода: - (NSArray *)sortEvents:(NSArray *)events { // Сортировка событий (Сначала кино, затем остальные, обе секции по алфавиту) NSMutableArray *cinemaEvents = [[NSMutableArray alloc] init]; NSMutableArray *otherEvents = [[NSMutableArray alloc] init]; for (Event *event in events) { if ([event.type isEqualToString:kCinemaEventType]) { [cinemaEvents addObject:event]; } else { [otherEvents addObject:event]; } } NSComparisonResult (^sortBlock)(Event *firstEvent, Event *secondEvent) = ^NSComparisonResult(Event *firstEvent, Event *secondEvent) { return [firstEvent.type compare:secondEvent.type options:NSNumericSearch]; }; [cinemaEvents sortUsingComparator:sortBlock]; [otherEvents sortUsingComparator:sortBlock]; return [cinemaEvents arrayByAddingObjectsFromArray:otherEvents]; }
  • 8. Примеры применения Как результат - инверсия ответственности в TDD
  • 9. Примеры применения Маппер должен уметь: 1) мапить объекты (неожиданно) 2) обрабатывать кривую выдачу (Null, неверный тип данных, неверная структура выдачи) 3) обеспечивать консистентность данных (проверка обязательных полей) Интерфейс тестируемого метода: - (NSArray *)mapEvents:(id)responseObject; Пример 2. Маппер
  • 10. Примеры применения Тест: - (void)testMapEventsResponseSuccessful { // given NSDictionary *responseObject = @{kEventResponseKey : @[@{@"type" : @1, @"name" : @"test", @"description" : @"test"}]}; // when NSArray *events = [self.mapper mapEvents:responseObject]; // then Event *event = events[0]; [self checkObject:event forKeyExistence:@[@"type", @"name", @"description"]]; } - (void)checkObject:(id)object forKeyExistence:(NSArray *)keys { for (NSString *key in keys) { if (![object valueForKey:key]) { XCTFail(@"Объект не содержит необходимого поля - %@", key); } } }
  • 11. Примеры применения Реализация метода: - (NSArray *)mapEvents:(id)responseObject { NSDictionary *mappingsDictionary = @{kEventResponseKey : [self eventResponseMapping]}; RKMappingResult *mappingResult = [self mapResponseObject:responseObject withMappingsDictionary:mappingsDictionary]; if (mappingResult) { return [mappingResult array]; } return @[]; }
  • 12. Примеры применения Тест: - (void)testMapEventsResponseWithMissingMandatoryFields { // given NSDictionary *responseObject = @{kEventResponseKey : @[@{@"name" : @"test"}]}; // when NSArray *events = [self.mapper mapEvents:responseObject]; // then XCTAssertFalse([events count]); } Реализация метода: - (NSArray *)mapEvents:(id)responseObject { NSDictionary *mappingsDictionary = @{kEventResponseKey : [self eventResponseMapping]}; RKMappingResult *mappingResult = [self mapResponseObject:responseObject withMappingsDictionary:mappingsDictionary]; if (mappingResult) { //Проверяем наличие обязательных полей в объекте NSArray *events = [self checkMandatoryFields:[mappingResult array]]; return events; } return @[]; }
  • 13. Примеры применения Тест: - (void)testMapEventsResponseWithNulls { // given NSDictionary *responseObject = @{kEventResponseKey : @[@{@"type" : @1, @"name" : [NSNull null], @"description" : [NSNull null]}]}; // when NSArray *events = [self.mapper mapEvents:responseObject]; // then Event *event = events[0]; XCTAssertNotNil(event.type, @""); XCTAssertNil(event.name, @""); } - (void)testMapEventsResponseWithWrongType { // given NSDictionary *responseObject = @{kEventResponseKey : @[@{@"type" : @"123"}]}; // when NSArray *events = [self.mapper mapEvents:responseObject]; // then Event *event = events[0]; XCTAssertTrue([event.type isEqual:@123]); }
  • 14. Примеры применения Тест: - (void)testMapPlanResponseWithDrunkenResponseStructure { // given NSArray *responseObject = @[@{@"test" : @[]}, @{@"test" : @"test"}]; // when NSArray *events = [self.mapper mapEvents:responseObject]; // then XCTAssertFalse([events count]); }
  • 15. Преимущества и недостатки Преимущества Недостатки Продумывание интерфейса до реализации Сложность применения (безопасность данных, UI, базы данных) Меньше отладки Больше времени Уверенность при изменении Ложное ощущение надежности Меньше ошибок Ошибка в тесте Документация тестами Поддержка тестов Модульность Полноценные тесты
  • 16. Преимущества и недостатки Разработка через тестирование поощряет простой дизайн и внушает уверенность. TDD encourages simple designs and inspires confidence. Кент Бек
  • 17. Литература и ссылки Kent Beck – Test-Driven Development: By example http://www.objc.io/issue-15/ https://en.wikipedia.org/wiki/Test-driven_development http://qualitycoding.org/objective-c-tdd/ http://agiledata.org/essays/tdd.html#WhatIsTDD http://www.basilv.com/psd/blog/2009/test-driven-development-benefits-limitations-and- techniques http://martinfowler.com/articles/is-tdd-dead/ http://habrahabr.ru/post/206828/ http://habrahabr.ru/post/216923/ http://iosunittesting.com/