SlideShare a Scribd company logo
Разработка через
                                                 тестирование
                                       iOS, Bowling Game Kata
                                               Test Driven Development

                                          Ivan Dyachenko <ivan.dyachenko@gmail.com>
© Luxoft Training 2012




                                                                 http://uamobile.in.ua/




            Thursday, December 6, 12
Kent Beck


                                       Экстремальное
                                       программирование (XP)

                                       Разработка через
                                       тестирование (TDD)

                                       Agile Manifesto в 2001
                                       году.
© Luxoft Training 2012




            Thursday, December 6, 12
Whole
                                                             Team


                                       Collective                                  Coding
                                                           Test-Driven
                                       Ownership                                  Standard
                                                          Development


                         Customer           Pair                                                Planning
                                                                              Refactoring
                           Tests       Programming                                               Game


                                    Continuous                                    Sustainable
                                                          Simple Design
                                    Integration                                      Pace
                                                            Metaphor
                                                             Small
                                                            Releases
© Luxoft Training 2012




                                                  Extreme Programming Practices


            Thursday, December 6, 12
Whole
                                                             Team


                                       Collective                                  Coding
                                                           Test-Driven
                                       Ownership                                  Standard
                                                          Development


                         Customer           Pair                                                Planning
                                                                              Refactoring
                           Tests       Programming                                               Game


                                    Continuous                                    Sustainable
                                                          Simple Design
                                    Integration                                      Pace
                                                            Metaphor
                                                             Small
                                                            Releases
© Luxoft Training 2012




                                                  Extreme Programming Practices


            Thursday, December 6, 12
TDD




                                       «Чистый код, который работает»
© Luxoft Training 2012




            Thursday, December 6, 12
Мифы TDD



                                       Unit tests == TDD


                                       TDD == 100% coverage


                                       TDD == время * 2


                                       TDD == серебряная пуля
© Luxoft Training 2012




            Thursday, December 6, 12
Два простых правила TDD




                               1       Пишем новый код только тогда, когда
                                       автоматический код не сработал



                               2       Удаляем дублирование
© Luxoft Training 2012




            Thursday, December 6, 12
© Luxoft Training 2012




                                       Мантра TDD – “red, green, refactor”




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай
© Luxoft Training 2012




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай

                               1       Напиши тест
© Luxoft Training 2012




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай

                               1       Напиши тест

                               2       Скомпилируй
© Luxoft Training 2012




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай

                               1       Напиши тест

                               2       Скомпилируй

                               3       Исправь ошибки
© Luxoft Training 2012




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай

                               1       Напиши тест

                               2       Скомпилируй

                               3       Исправь ошибки

                               4       Запусти и убедись что тесты упали
© Luxoft Training 2012




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай

                               1       Напиши тест

                               2       Скомпилируй

                               3       Исправь ошибки

                               4       Запусти и убедись что тесты упали

                               5       Напиши код
© Luxoft Training 2012




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай

                               1       Напиши тест

                               2       Скомпилируй

                               3       Исправь ошибки

                               4       Запусти и убедись что тесты упали

                               5       Напиши код

                               6       Запусти и убедись что тесты прошли
© Luxoft Training 2012




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай

                               1       Напиши тест

                               2       Скомпилируй

                               3       Исправь ошибки

                               4       Запусти и убедись что тесты упали

                               5       Напиши код

                               6       Запусти и убедись что тесты прошли
© Luxoft Training 2012




                               7       Рефакторинг




            Thursday, December 6, 12
RED / GREEN / REFACTOR

                               0       Подумай

                               1       Напиши тест

                               2       Скомпилируй

                               3       Исправь ошибки




                                                                            Повтори
                               4       Запусти и убедись что тесты упали

                               5       Напиши код

                               6       Запусти и убедись что тесты прошли
© Luxoft Training 2012




                               7       Рефакторинг




            Thursday, December 6, 12
Ошибки TDD



                                       Писать тест после кода



                                       Писать тест который сразу проходит



                                       Писать сразу много тестов
© Luxoft Training 2012




            Thursday, December 6, 12
Инструменты

                           § OCUnit/SenTestingKit начиная IPhone SDK 2.2

                           § GHUnit

                           § Google Toolkit for Mac

                           § OCMock

                           § OCHamcrest

                           § Kiwi

                           § Cedar

                           § …
© Luxoft Training 2012




            Thursday, December 6, 12
OCUnit
                          § Object-oriented tests

                          § Very low overhead

                          § Tests are in the same language as the implementation

                          § Test case classes cohabit with classes they test

                          § Promotes aggressive refactoring

                          § Helps capture requirements, expose dependencies

                          § Total integration in the development process

                          § Records testing expertise
© Luxoft Training 2012




                          § Tests frameworks, bundles, or applications

                          § Easy installation
            Thursday, December 6, 12
OCUnit

                                            Asserts                 TestCase

                           § STAssertNil             § test<Test Case>

                           § STAssertNotNil          § setUp

                           § STAssertTrue            § tearDown

                           § STAssertFalse

                           § STAssertEquals

                           § STAssertEqualObjects

                           § STFail
© Luxoft Training 2012




                           § ...

            Thursday, December 6, 12
Пример




                                       Bowling Game Kata - подсчет очков игры в боулинг




                                                   www.objectmentor.com
                                                     wiki.agiledev.ru
© Luxoft Training 2012




                                                    www.slideshare.net




            Thursday, December 6, 12
© Luxoft Training 2012




            Thursday, December 6, 12
Правила игры в боулинг

                                          Раунды                              Подсчет очков

                           § 10 раундов (frame-ов)                § 10 сразу (strike). Заканчивается
                                                                      досрочно.
                           § В одном  frame – 2 броска               10 очков + pins + pins

                           § Цель – выбить кегли (pins)           § 10 очков со второго броска
                                                                      (spare)
                           § Выигрывает набравший больше             10 очков + pins
                             всех очков
                                                                   § Max 300 очков (12 strikes)
                                                           Последний frame

                           § 1-й strike – дает возможность бросить еще два раза
© Luxoft Training 2012




                           § 2-й spare – дает возможность бросить еще одни раз


            Thursday, December 6, 12
Надо написать

                                                      BowlingGame
                                                   + roll(pins : int)
                                                   + score() : int




                               Написать класс BowlingGame, который имеет два метода

                               • roll (pins : int) – вызывается каждый раз когда игрок
                                  бросает шар. Pins – количество выбитых кеглей в этом
                                  броске

                               • score() : int – вызывается в конце игры. Показывает
                                  результат игры
© Luxoft Training 2012




            Thursday, December 6, 12
A quick design session

                                                  Нам нужен
                                               BowlingGame класс
                             BowlingGame

                          + roll(pins : int)
© Luxoft Training 2012




            Thursday, December 6, 12
A quick design session


                             BowlingGame                               Frame

                          + roll(pins : int)                   + score() : int




                                               Игра имеет 10
                                                 фреймов
© Luxoft Training 2012




            Thursday, December 6, 12
A quick design session


                             BowlingGame               Frame                            Roll

                          + roll(pins : int)   + score() : int                - pins : int




                                                               Каждый фрейм
                                                            состоит из одного или
                                                                двух бросков
© Luxoft Training 2012




            Thursday, December 6, 12
A quick design session


                             BowlingGame                  Frame               Roll

                          + roll(pins : int)      + score() : int   - pins : int




                                                     Tenth Frame
                             Последний фрейм
© Luxoft Training 2012




                           содержит два или три
                                  броска



            Thursday, December 6, 12
A quick design session


                              BowlingGame                Frame               Roll

                           + roll(pins : int)    + score() : int   - pins : int




                          Score функция должна
                            пройтись по всем
                          фреймам и посчитать
                                результат           Tenth Frame
© Luxoft Training 2012




            Thursday, December 6, 12
A quick design session                     Strike или Spare
                                                                 зависит от количества
                                                   Next Frame      выбитых кеглей в
                                                                          Frame


                             BowlingGame               Frame                  Roll

                          + roll(pins : int)   + score() : int      - pins : int




                                                  Tenth Frame
© Luxoft Training 2012




            Thursday, December 6, 12
Готовим среду для тестирования




                                                 +
© Luxoft Training 2012




            Thursday, December 6, 12
Еще раз повторим правила

                                          Раунды                              Подсчет очков

                           § 10 раундов (frame-ов)                § 10 сразу (strike). Заканчивается
                                                                      досрочно.
                           § В одном  frame – 2 броска               10 очков + pins + pins

                           § Цель – выбить кегли (pins)           § 10 очков со второго броска
                                                                      (spare)
                           § Выигрывает набравший больше             10 очков + pins
                             всех очков
                                                                   § Max 300 очков (12 strikes)
                                                           Последний frame

                           § 1-й strike – дает возможность бросить еще два раза
© Luxoft Training 2012




                           § 2-й spare – дает возможность бросить еще одни раз


            Thursday, December 6, 12
Пишем код
© Luxoft Training 2012




            Thursday, December 6, 12
Test List
                          /*

                           should   score   zero on gutter game    Подумай
                           should   score   twenty when all one
                           should   score   spare correctly
                           should   score   all spares correctly
                           should   score   strike correctly
                           should   score   super game

                           */

                          #import "BowlingGameTests.h”

                          @implementation BowlingGameTests

                          - (void)setUp
                          {
                              [super setUp];
                          }

                          - (void)tearDown
                          {
                              [super tearDown];
© Luxoft Training 2012




                          }

                          @end



            Thursday, December 6, 12
Assert First
                          - (void)testGutterGame
                          {
                              STAssertEquals(0, [game score], nil);
                          }
© Luxoft Training 2012




            Thursday, December 6, 12
Test First
                          - (void)testGutterGame
                          {
                              BowlingGame *game = [[BowlingGame alloc] init];
                              for (int i = 0; i < 20; i++) {
                                  [game roll:0];
                              }
                              STAssertEquals(0, [game score], nil);
                          }


                                                                    Пишем тест
                                                                игнорируя ошибки
                                                                   компилятора
© Luxoft Training 2012




            Thursday, December 6, 12
Исправляем ошибки, пишем код
                         - (void)testGutterGame
                         {
                             BowlingGame *game = [[BowlingGame alloc] init];
                             for (int i = 0; i < 20; i++) {
                                 [game roll:0];
                             }
                             STAssertEquals(0, [game score], nil);
                         }



                         @implementation BowlingGame

                         - (void)roll:(int)pins {

                         }

                         - (int)score {         Пишем минимум
                             return 0;            кода! KISS
                         }
© Luxoft Training 2012




                         @end



            Thursday, December 6, 12
Следующий тест
                         - (void)testAllOne                       Тест падает
                         {
                             BowlingGame *game = [[BowlingGame alloc] init];
                             for (int i = 0; i < 20; i++) {
                                 [game roll:1];
                             }
                             STAssertEquals(20, [game score], nil);
                         }
© Luxoft Training 2012




            Thursday, December 6, 12
Пишем код
                         - (void)testAllOne
                         {
                             BowlingGame *game = [[BowlingGame alloc] init];
                             for (int i = 0; i < 20; i++) {
                                 [game roll:1];                                Тест проходит
                             }
                             STAssertEquals(20, [game score], nil);
                         }




                         #import "BowlingGame.h"

                         @implementation BowlingGame

                         - (void)roll:(int)pins {
                             score += pins;
                         }

                         - (int)score {
                             return score;
                         }
© Luxoft Training 2012




                         @end




            Thursday, December 6, 12
Убираем дублирование
                         - (void)testGutterGame
                         {
                             int n = 20;
                             int pins = 0;
                             for (int i = 0; i < n; i++) {
                                 [game roll:pins];
                             }
                             STAssertEquals(0, [game score], nil);
                         }
© Luxoft Training 2012




            Thursday, December 6, 12
Рефакторим

                         - (void)testGutterGame
                         {
                             [self rollMany:0 times:20];
                             STAssertEquals(0, [game score], nil);
                         }

                         - (void)testAllOne
                         {
                             [self rollMany:1 times:20];
                             STAssertEquals(20, [game score], nil);
                         }

                         - (void)rollMany:(int)pins times:(int)n
                         {
                             for (int i = 0; i < n; i++) {
                                 [game roll:pins];
                             }
                         }
© Luxoft Training 2012




            Thursday, December 6, 12
Проверка на Spare

                           6           3
                                                                       Тест падает
                               4               -

                           10 + 3          3

                          - (void)testScoreSpare {
                              [game roll:5]; // spare
                              [game roll:5];
                              [game roll:3];
                              [self rollMany:17 times:0];
                              STAssertEquals(16, [game score], nil);
                          }
© Luxoft Training 2012




            Thursday, December 6, 12
Design review
                         #import "BowlingGame.h"              roll – занимается
                                                             подсчетом очков, но
                         @implementation BowlingGame           имя метода не
                                                              указывает на это
                         - (void)roll:(int)pins {
                             score += pins;
                         }

                         - (int)score {
                             return score;
                         }
                                         score – не занимается подсчетом
                         @end
                                          очков, хотя имя указывает, что
                                                      должна
© Luxoft Training 2012




            Thursday, December 6, 12
Redesign                         Добавляем метод
                                                              в Ignore
                         //- (void)testScoreSpare {
                         //    [game roll:5]; // spare
                         //    [game roll:5];
                         //    [game roll:3];
                         //    [self rollMany:17 times:0];
                         //    STAssertEquals(16, [game score], nil);
                         //}
© Luxoft Training 2012




            Thursday, December 6, 12
Redesign
                         #import "BowlingGame.h"

                         @implementation BowlingGame

                         - (void)roll:(int)pins {
                             rolls[currentRoll++] = pins;
                         }

                         - (int)score {
                             int score = 0;
                             for (int i = 0; i < 20; i++)
                                 score += rolls[i];
                             return score;
                         }

                         @end
© Luxoft Training 2012




            Thursday, December 6, 12
Убираем Ignore
                          - (void)testScoreSpare {
                              [game roll:5]; // spare
                              [game roll:5];
                              [game roll:3];                           Тест падает
                              [self rollMany:17 times:0];
                              STAssertEquals(16, [game score], nil);
                          }
© Luxoft Training 2012




            Thursday, December 6, 12
Пишем код
                         - (int)score {
                             int score = 0;
                             for (int i = 0; i < 20; i++)
                                 if (rolls[i] + rolls[i + 1] == 10) //spare
                                     score += 10 + rolls[i + 2];
                                 ...
                                 score += rolls[i];
                             return score;
                         }
                                                        Хорошая идея! За одним
                                                     исключением – это не работает

                         У нас все еще проблемы с дизайном.
                         Очевидно, надо считать очки по фреймам
© Luxoft Training 2012




            Thursday, December 6, 12
Очередная сессия Redesign
                         //- (void)testScoreSpare {
                         //    [game roll:5]; // spare
                         //    [game roll:5];
                         //    [game roll:3];
                         //    [self rollMany:17 times:0];
                         //                                       Добавляем метод
                               STAssertEquals(16, [game score], nil);
                         //}                                          в Ignore
© Luxoft Training 2012




            Thursday, December 6, 12
Refactoring
                         - (int)score {
                             int score = 0;
                             int i = 0;
                             for (int frame = 0; frame < 10; frame++) {
                                 score += rolls[i] + rolls[i + 1];
                                 i += 2;
                             }
                             return score;
                         }
© Luxoft Training 2012




            Thursday, December 6, 12
Убираем Ignore
                          - (void)testScoreSpare {
                              [game roll:5]; // spare
                              [game roll:5];
                                                                       Тест падает
                              [game roll:3];
                              [self rollMany:17 times:0];
                              STAssertEquals(16, [game score], nil);
                          }
© Luxoft Training 2012




            Thursday, December 6, 12
Пишем код
                         - (int)score {
                             int score = 0;
                             int i = 0;
                             for (int frame =   0; frame < 10; frame++) {
                                 if (rolls[i]   + rolls[i + 1] == 10) {// spare
                                     score +=   10 + rolls[i + 2];
                                     i += 2;
                                 }
                                 else {
                                     score +=   rolls[i] + rolls[i + 1];
                                     i += 2;
                                 }
                             }
                             return score;
                         }
© Luxoft Training 2012




            Thursday, December 6, 12
Design review   Плохое имя переменной

                         - (int)score {
                             int score = 0;
                             int i = 0;
                             for (int frame =   0; frame < 10; frame++) {
                                 if (rolls[i]   + rolls[I + 1] == 10) {// spare
                                     score +=   10 + rolls[i + 2];
                                     i += 2;
                                 }                          Плохо иметь комментарий в
                                 else {                              условии
                                     score +=   rolls[i] + rolls[i + 1];
                                     i += 2;
                                 }
                             }
                             return score;
                         }
© Luxoft Training 2012




            Thursday, December 6, 12
Refactoring
                          - (int)score {
                              int score = 0;
                              int ballIndex = 0;
                              for (int frame = 0; frame < 10; frame++) {
                                  if ([self isSpare:ballIndex]) {
                                      score += 10 + rolls[ballIndex + 2];
                                      ballIndex += 2;
                                  }
                                  else {
                                      score += rolls[ballIndex] + rolls[ballIndex + 1];
                                      ballIndex += 2;
                                  }
                              }
                              return score;
                          }

                          - (BOOL)isSpare:(int)ballIndex {
© Luxoft Training 2012




                              return rolls[ballIndex] + rolls[ballIndex+1] == 10;
                          }



            Thursday, December 6, 12
Проверка на Strike

                           10          3

                                *          4

                          10 + 3 + 4   3+4
                                                          Комментарий в тесте
                          - (void)testScoreStrike {
                              [game roll:10]; // strike
                              [game roll:3];
                              [game roll:4];
                              [self rollMany:16 times:0];
                              STAssertEquals(24, [game score], nil);
                          }
© Luxoft Training 2012




            Thursday, December 6, 12
Пишем код
                          - (int)score {
                              int score = 0;
                              int ballIndex = 0;
                              for (int frame = 0; frame < 10; frame++) {
                                  if (rolls[ballIndex] == 10) {
                                      score += 10 +
                          !   !  !   !   !   !   rolls[ballIndex + 1] + ! !   !
                          !   !  !   !   !   !   rolls[ballIndex + 2];
                                      ballIndex++;
                                  }
                                  else if ([self isSpare:ballIndex]) {
                                      score += 10 + rolls[ballIndex + 2];
                                      ballIndex += 2;
                                  }
                                  else {
                                      score += rolls[ballIndex] + rolls[ballIndex + 1];
                                      ballIndex += 2;
                                  }
                              }
© Luxoft Training 2012




                              return score;
                          }



            Thursday, December 6, 12
Design review
                         - (int)score {
                             int score = 0;                 Комментарий    для условия
                             int ballIndex = 0;
                             for (int frame = 0; frame < 10; frame++) {
                                 if (rolls[ballIndex] == 10) { // strike
                                     score += 10 +
                                         rolls[ballIndex + 1] +
                                         rolls[ballIndex + 2];
                                     ballIndex++;
                                 }
                                 else if ([self isSpare:ballIndex]) {
                                     score += 10 +
                                         rolls[ballIndex + 2];
                                     ballIndex += 2;
                                 }
                                 else {
                                     score +=
                                         rolls[ballIndex] +
                                         rolls[ballIndex + 1];
                                     ballIndex += 2;
                                 }
                             }
                             return score;
© Luxoft Training 2012




                         }
                                                            Непонятное
                                                           выражение



            Thursday, December 6, 12
Refactoring
                         - (int)score {
                             int score = 0;
                             int ballIndex = 0;
                             for (int frame = 0; frame < 10; frame++) {
                                 if ([self isStrike:ballIndex]) {
                                     score += 10 + [self strikeBonus:ballIndex];
                                     ballIndex++;
                                 }
                                 else if ([self isSpare:ballIndex]) {
                                     score += 10 + [self spareBonus:ballIndex];
                                     ballIndex += 2;
                                 }
                                 else {
                                     score += [self sumOfBallsInFrame:ballIndex];
                                     ballIndex += 2;
                                 }
                             }
                             return score;
                         }
© Luxoft Training 2012




            Thursday, December 6, 12
Refactoring
                         - (void)testScoreStrike {
                             [self rollStrike];
                             [game roll:3];
                             [game roll:4];
                             [self rollMany:16 times:0];
                             STAssertEquals(24, [game score], nil);
                         }

                         - (void)rollStrike {
                             [game roll:10];
                         }
© Luxoft Training 2012




                         git checkout bowling-0.8

            Thursday, December 6, 12
Контрольный пример
                         - (void)testPrefectGame {
                             [self rollMany:10 times:12];
                             STAssertEquals(300, [game score], nil);
                         }
© Luxoft Training 2012




            Thursday, December 6, 12
Cтратегии запуска тестов

                         § IDE

                         § Console

                         § CocoaPods

                         § Maven

                         § Test Runner

                         § CI

                         § File watcher
© Luxoft Training 2012




            Thursday, December 6, 12
Continuous integration




                              Hudson
                                                  Team City
© Luxoft Training 2012




            Thursday, December 6, 12
Преимущества от TDD


                                       Меньше ошибок


                                       Проще рефакторить


                                       Документация


                                       Лучший дизайн кода


                                       Быстрее процесс разработки
© Luxoft Training 2012




            Thursday, December 6, 12
BDD


                                       Behavior Driven Development (BDD)
© Luxoft Training 2012




            Thursday, December 6, 12
BDD – что это?




                                          Language
© Luxoft Training 2012




            Thursday, December 6, 12
Difference between TDD, BDD & ATDD


                                 TDD                         ATDD
© Luxoft Training 2012




            Thursday, December 6, 12
BDD

                                DDD-Domain Driven Testing + DSL + GIVEN / WHEN / THEN




                                       Спецификация


                                       Тесты


                                       Документация
© Luxoft Training 2012




            Thursday, December 6, 12
Kiwi
                         describe(@"BowlingGame", ^{

                            it(@"should score zero on gutter game", ^{
                                rollMany(20, 0);
                                [[theValue([game score]) should] equal:theValue(0)];
                            });

                            it(@"should score twenty when all one", ^{
                                rollMany(20, 1);
                                [[theValue([game score]) should] equal:theValue(20)];
                            });

                            it(@"should score spare correctly", ^{
                                [game roll:5];
                                [game roll:5];
                                [game roll:3];
                                rollMany(17, 0);
                                [[theValue([game score]) should] equal:theValue(16)];
                            });

                            it(@"should score strike correctly", ^{
                                [game roll:10];
                                [game roll:3];
© Luxoft Training 2012




                                [game roll:4];
                                rollMany(16, 0);
                                [[theValue([game score]) should] equal:theValue(24)];
                            });


            Thursday, December 6, 12
© Luxoft Training 2012




            Thursday, December 6, 12
© Luxoft Training 2012




            Thursday, December 6, 12
*.feature
                          # language: ru
                          Функционал: Авторизация пользователей

                          	   Чтобы указывать себя автором снипетов, голосовать за 	
                          	   снипеты и нарабатывать карму, пользователи должны иметь 	
                          	   возможность регистрироваться

                          	   Сценарий: Успешная авторизация с указываемыми логином и паролем
                          	   Допустим я зарегистрированный пользователь "User12" с паролем "User1212"
                          	   И я на странице Авторизация
                          	   Если ввожу в поле Логин "User12"
                          	   И ввожу в поле Пароль "User1212"
                          	   И кликаю кнопку "Войти"
                          	   То я должен увидеть уведомление "Добро пожаловать!"
                          	   И я должен оказаться на странице Страница пользователя
© Luxoft Training 2012




            Thursday, December 6, 12
*.feature
© Luxoft Training 2012




            Thursday, December 6, 12
Вопросы ?
© Luxoft Training 2012




            Thursday, December 6, 12
Разработка через тестирование


                                                                                IDyachenko@luxoft.com




                                          git clone git://github.com/ivan-dyachenko/Trainings.git
© Luxoft Training 2012




                                          https://github.com/ivan-dyachenko/Trainings




            Thursday, December 6, 12

More Related Content

Viewers also liked

[144]mobile앱에서 효율적인 storage 접근 방법
[144]mobile앱에서 효율적인 storage 접근 방법[144]mobile앱에서 효율적인 storage 접근 방법
[144]mobile앱에서 효율적인 storage 접근 방법
NAVER D2
 
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
SangIn Choung
 
애자일에대한오해와진실
애자일에대한오해와진실애자일에대한오해와진실
애자일에대한오해와진실Sangcheol Hwang
 
When develpment met test(shift left testing)
When develpment met test(shift left testing)When develpment met test(shift left testing)
When develpment met test(shift left testing)
SangIn Choung
 
테스트자동화 성공전략
테스트자동화 성공전략테스트자동화 성공전략
테스트자동화 성공전략
SangIn Choung
 
스크럼, 이걸 왜 하나요
스크럼, 이걸 왜 하나요스크럼, 이걸 왜 하나요
스크럼, 이걸 왜 하나요
Insub Lee
 
소프트웨어 테스팅
소프트웨어 테스팅소프트웨어 테스팅
소프트웨어 테스팅영기 김
 

Viewers also liked (7)

[144]mobile앱에서 효율적인 storage 접근 방법
[144]mobile앱에서 효율적인 storage 접근 방법[144]mobile앱에서 효율적인 storage 접근 방법
[144]mobile앱에서 효율적인 storage 접근 방법
 
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
 
애자일에대한오해와진실
애자일에대한오해와진실애자일에대한오해와진실
애자일에대한오해와진실
 
When develpment met test(shift left testing)
When develpment met test(shift left testing)When develpment met test(shift left testing)
When develpment met test(shift left testing)
 
테스트자동화 성공전략
테스트자동화 성공전략테스트자동화 성공전략
테스트자동화 성공전략
 
스크럼, 이걸 왜 하나요
스크럼, 이걸 왜 하나요스크럼, 이걸 왜 하나요
스크럼, 이걸 왜 하나요
 
소프트웨어 테스팅
소프트웨어 테스팅소프트웨어 테스팅
소프트웨어 테스팅
 

Similar to Tdd objective c

TDD (Test-driven Development) как стиль разработки.
TDD (Test-driven Development) как стиль разработки.TDD (Test-driven Development) как стиль разработки.
TDD (Test-driven Development) как стиль разработки.
Pavel Tsukanov
 
Bdd with java using concordion and selenium ui tests
Bdd with java using concordion and selenium ui testsBdd with java using concordion and selenium ui tests
Bdd with java using concordion and selenium ui testsautomated-testing.info
 
Bdd with java_using_concordion_and_selenium_ui_tests
Bdd with java_using_concordion_and_selenium_ui_testsBdd with java_using_concordion_and_selenium_ui_tests
Bdd with java_using_concordion_and_selenium_ui_tests
Oleksiy Rezchykov
 
Практика работы с крупными проектами - от Scrum с XP к Kanban
Практика работы с крупными проектами - от Scrum с XP к KanbanПрактика работы с крупными проектами - от Scrum с XP к Kanban
Практика работы с крупными проектами - от Scrum с XP к KanbanAlexander Byndyu
 
Process improvement process improvement process
Process improvement process improvement processProcess improvement process improvement process
Process improvement process improvement process
Askhat Urazbaev
 
уразбаев асхат - процесс улучшения процесса улучшения процесса
уразбаев асхат - процесс улучшения процесса улучшения процессауразбаев асхат - процесс улучшения процесса улучшения процесса
уразбаев асхат - процесс улучшения процесса улучшения процесса
Magneta AI
 
Coding dojo
Coding dojoCoding dojo
Coding dojo
Evgeny Shepelyuk
 
Ромуальд Здебский, Обеспечение качества через интегрированное управление прое...
Ромуальд Здебский, Обеспечение качества через интегрированное управление прое...Ромуальд Здебский, Обеспечение качества через интегрированное управление прое...
Ромуальд Здебский, Обеспечение качества через интегрированное управление прое...
SQADays_2009_Piter
 
Вебинар Microsoft ALM (11.12.2012)
Вебинар Microsoft ALM (11.12.2012)Вебинар Microsoft ALM (11.12.2012)
Вебинар Microsoft ALM (11.12.2012)Dmitry Melikov
 

Similar to Tdd objective c (10)

TDD (Test-driven Development) как стиль разработки.
TDD (Test-driven Development) как стиль разработки.TDD (Test-driven Development) как стиль разработки.
TDD (Test-driven Development) как стиль разработки.
 
Techsystem mentor
Techsystem mentorTechsystem mentor
Techsystem mentor
 
Bdd with java using concordion and selenium ui tests
Bdd with java using concordion and selenium ui testsBdd with java using concordion and selenium ui tests
Bdd with java using concordion and selenium ui tests
 
Bdd with java_using_concordion_and_selenium_ui_tests
Bdd with java_using_concordion_and_selenium_ui_testsBdd with java_using_concordion_and_selenium_ui_tests
Bdd with java_using_concordion_and_selenium_ui_tests
 
Практика работы с крупными проектами - от Scrum с XP к Kanban
Практика работы с крупными проектами - от Scrum с XP к KanbanПрактика работы с крупными проектами - от Scrum с XP к Kanban
Практика работы с крупными проектами - от Scrum с XP к Kanban
 
Process improvement process improvement process
Process improvement process improvement processProcess improvement process improvement process
Process improvement process improvement process
 
уразбаев асхат - процесс улучшения процесса улучшения процесса
уразбаев асхат - процесс улучшения процесса улучшения процессауразбаев асхат - процесс улучшения процесса улучшения процесса
уразбаев асхат - процесс улучшения процесса улучшения процесса
 
Coding dojo
Coding dojoCoding dojo
Coding dojo
 
Ромуальд Здебский, Обеспечение качества через интегрированное управление прое...
Ромуальд Здебский, Обеспечение качества через интегрированное управление прое...Ромуальд Здебский, Обеспечение качества через интегрированное управление прое...
Ромуальд Здебский, Обеспечение качества через интегрированное управление прое...
 
Вебинар Microsoft ALM (11.12.2012)
Вебинар Microsoft ALM (11.12.2012)Вебинар Microsoft ALM (11.12.2012)
Вебинар Microsoft ALM (11.12.2012)
 

More from UA Mobile

Владимир Кириллов-TCP-Performance for-Mobile-Applications
Владимир Кириллов-TCP-Performance for-Mobile-ApplicationsВладимир Кириллов-TCP-Performance for-Mobile-Applications
Владимир Кириллов-TCP-Performance for-Mobile-ApplicationsUA Mobile
 
Денис Лебедев-Управление зависимостями с помощью CocoaPods
Денис Лебедев-Управление зависимостями с помощью CocoaPodsДенис Лебедев-Управление зависимостями с помощью CocoaPods
Денис Лебедев-Управление зависимостями с помощью CocoaPodsUA Mobile
 
Дмитрий Малеев-Мобильная Геймификация или как вырабатывать-привычки
Дмитрий Малеев-Мобильная Геймификация или как вырабатывать-привычкиДмитрий Малеев-Мобильная Геймификация или как вырабатывать-привычки
Дмитрий Малеев-Мобильная Геймификация или как вырабатывать-привычкиUA Mobile
 
Александр Терещук - Memory Analyzer Tool and memory optimization tips in Android
Александр Терещук - Memory Analyzer Tool and memory optimization tips in AndroidАлександр Терещук - Memory Analyzer Tool and memory optimization tips in Android
Александр Терещук - Memory Analyzer Tool and memory optimization tips in AndroidUA Mobile
 
Максим Щеглов - Google Cloud Messaging for Android
Максим Щеглов - Google Cloud Messaging for AndroidМаксим Щеглов - Google Cloud Messaging for Android
Максим Щеглов - Google Cloud Messaging for AndroidUA Mobile
 
Александр Додатко - Работа с датами в ObjectiveC и SQLite
Александр Додатко - Работа с датами в ObjectiveC и SQLiteАлександр Додатко - Работа с датами в ObjectiveC и SQLite
Александр Додатко - Работа с датами в ObjectiveC и SQLiteUA Mobile
 
Сергей Арнаут - Stream yourself with Android
Сергей Арнаут - Stream yourself with AndroidСергей Арнаут - Stream yourself with Android
Сергей Арнаут - Stream yourself with AndroidUA Mobile
 
Михаил Галушко - Разработка WinRT приложений для Windows 8: реальный опыт
Михаил Галушко -  Разработка WinRT приложений для Windows 8: реальный опытМихаил Галушко -  Разработка WinRT приложений для Windows 8: реальный опыт
Михаил Галушко - Разработка WinRT приложений для Windows 8: реальный опытUA Mobile
 
Дмитрий Вовк - Learn iOS Game Optimization. Ultimate Guide
Дмитрий Вовк - Learn iOS Game Optimization. Ultimate GuideДмитрий Вовк - Learn iOS Game Optimization. Ultimate Guide
Дмитрий Вовк - Learn iOS Game Optimization. Ultimate GuideUA Mobile
 
Павел Юрийчук - Разработка приложений под мобильные браузеры
Павел Юрийчук - Разработка приложений под мобильные браузерыПавел Юрийчук - Разработка приложений под мобильные браузеры
Павел Юрийчук - Разработка приложений под мобильные браузерыUA Mobile
 
Вадим Розов- Разработка под Blackberry. Подводные грабли
Вадим Розов- Разработка под Blackberry. Подводные граблиВадим Розов- Разработка под Blackberry. Подводные грабли
Вадим Розов- Разработка под Blackberry. Подводные граблиUA Mobile
 
Олег Апостол - Плюсы и минусы различных тач-платформ глазами веб-разработчика
Олег Апостол - Плюсы и минусы различных тач-платформ глазами веб-разработчикаОлег Апостол - Плюсы и минусы различных тач-платформ глазами веб-разработчика
Олег Апостол - Плюсы и минусы различных тач-платформ глазами веб-разработчикаUA Mobile
 
Евгений Галкин-Рекламные возможности Google для продвижения мобильных приложений
Евгений Галкин-Рекламные возможности Google для продвижения мобильных приложенийЕвгений Галкин-Рекламные возможности Google для продвижения мобильных приложений
Евгений Галкин-Рекламные возможности Google для продвижения мобильных приложенийUA Mobile
 
Алексей Лельчук - От аутсорсинга к продуктам: трансформация компании и ментал...
Алексей Лельчук - От аутсорсинга к продуктам: трансформация компании и ментал...Алексей Лельчук - От аутсорсинга к продуктам: трансформация компании и ментал...
Алексей Лельчук - От аутсорсинга к продуктам: трансформация компании и ментал...UA Mobile
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobileUA Mobile
 

More from UA Mobile (15)

Владимир Кириллов-TCP-Performance for-Mobile-Applications
Владимир Кириллов-TCP-Performance for-Mobile-ApplicationsВладимир Кириллов-TCP-Performance for-Mobile-Applications
Владимир Кириллов-TCP-Performance for-Mobile-Applications
 
Денис Лебедев-Управление зависимостями с помощью CocoaPods
Денис Лебедев-Управление зависимостями с помощью CocoaPodsДенис Лебедев-Управление зависимостями с помощью CocoaPods
Денис Лебедев-Управление зависимостями с помощью CocoaPods
 
Дмитрий Малеев-Мобильная Геймификация или как вырабатывать-привычки
Дмитрий Малеев-Мобильная Геймификация или как вырабатывать-привычкиДмитрий Малеев-Мобильная Геймификация или как вырабатывать-привычки
Дмитрий Малеев-Мобильная Геймификация или как вырабатывать-привычки
 
Александр Терещук - Memory Analyzer Tool and memory optimization tips in Android
Александр Терещук - Memory Analyzer Tool and memory optimization tips in AndroidАлександр Терещук - Memory Analyzer Tool and memory optimization tips in Android
Александр Терещук - Memory Analyzer Tool and memory optimization tips in Android
 
Максим Щеглов - Google Cloud Messaging for Android
Максим Щеглов - Google Cloud Messaging for AndroidМаксим Щеглов - Google Cloud Messaging for Android
Максим Щеглов - Google Cloud Messaging for Android
 
Александр Додатко - Работа с датами в ObjectiveC и SQLite
Александр Додатко - Работа с датами в ObjectiveC и SQLiteАлександр Додатко - Работа с датами в ObjectiveC и SQLite
Александр Додатко - Работа с датами в ObjectiveC и SQLite
 
Сергей Арнаут - Stream yourself with Android
Сергей Арнаут - Stream yourself with AndroidСергей Арнаут - Stream yourself with Android
Сергей Арнаут - Stream yourself with Android
 
Михаил Галушко - Разработка WinRT приложений для Windows 8: реальный опыт
Михаил Галушко -  Разработка WinRT приложений для Windows 8: реальный опытМихаил Галушко -  Разработка WinRT приложений для Windows 8: реальный опыт
Михаил Галушко - Разработка WinRT приложений для Windows 8: реальный опыт
 
Дмитрий Вовк - Learn iOS Game Optimization. Ultimate Guide
Дмитрий Вовк - Learn iOS Game Optimization. Ultimate GuideДмитрий Вовк - Learn iOS Game Optimization. Ultimate Guide
Дмитрий Вовк - Learn iOS Game Optimization. Ultimate Guide
 
Павел Юрийчук - Разработка приложений под мобильные браузеры
Павел Юрийчук - Разработка приложений под мобильные браузерыПавел Юрийчук - Разработка приложений под мобильные браузеры
Павел Юрийчук - Разработка приложений под мобильные браузеры
 
Вадим Розов- Разработка под Blackberry. Подводные грабли
Вадим Розов- Разработка под Blackberry. Подводные граблиВадим Розов- Разработка под Blackberry. Подводные грабли
Вадим Розов- Разработка под Blackberry. Подводные грабли
 
Олег Апостол - Плюсы и минусы различных тач-платформ глазами веб-разработчика
Олег Апостол - Плюсы и минусы различных тач-платформ глазами веб-разработчикаОлег Апостол - Плюсы и минусы различных тач-платформ глазами веб-разработчика
Олег Апостол - Плюсы и минусы различных тач-платформ глазами веб-разработчика
 
Евгений Галкин-Рекламные возможности Google для продвижения мобильных приложений
Евгений Галкин-Рекламные возможности Google для продвижения мобильных приложенийЕвгений Галкин-Рекламные возможности Google для продвижения мобильных приложений
Евгений Галкин-Рекламные возможности Google для продвижения мобильных приложений
 
Алексей Лельчук - От аутсорсинга к продуктам: трансформация компании и ментал...
Алексей Лельчук - От аутсорсинга к продуктам: трансформация компании и ментал...Алексей Лельчук - От аутсорсинга к продуктам: трансформация компании и ментал...
Алексей Лельчук - От аутсорсинга к продуктам: трансформация компании и ментал...
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobile
 

Tdd objective c

  • 1. Разработка через тестирование iOS, Bowling Game Kata Test Driven Development Ivan Dyachenko <ivan.dyachenko@gmail.com> © Luxoft Training 2012 http://uamobile.in.ua/ Thursday, December 6, 12
  • 2. Kent Beck Экстремальное программирование (XP) Разработка через тестирование (TDD) Agile Manifesto в 2001 году. © Luxoft Training 2012 Thursday, December 6, 12
  • 3. Whole Team Collective Coding Test-Driven Ownership Standard Development Customer Pair Planning Refactoring Tests Programming Game Continuous Sustainable Simple Design Integration Pace Metaphor Small Releases © Luxoft Training 2012 Extreme Programming Practices Thursday, December 6, 12
  • 4. Whole Team Collective Coding Test-Driven Ownership Standard Development Customer Pair Planning Refactoring Tests Programming Game Continuous Sustainable Simple Design Integration Pace Metaphor Small Releases © Luxoft Training 2012 Extreme Programming Practices Thursday, December 6, 12
  • 5. TDD «Чистый код, который работает» © Luxoft Training 2012 Thursday, December 6, 12
  • 6. Мифы TDD Unit tests == TDD TDD == 100% coverage TDD == время * 2 TDD == серебряная пуля © Luxoft Training 2012 Thursday, December 6, 12
  • 7. Два простых правила TDD 1 Пишем новый код только тогда, когда автоматический код не сработал 2 Удаляем дублирование © Luxoft Training 2012 Thursday, December 6, 12
  • 8. © Luxoft Training 2012 Мантра TDD – “red, green, refactor” Thursday, December 6, 12
  • 9. RED / GREEN / REFACTOR 0 Подумай © Luxoft Training 2012 Thursday, December 6, 12
  • 10. RED / GREEN / REFACTOR 0 Подумай 1 Напиши тест © Luxoft Training 2012 Thursday, December 6, 12
  • 11. RED / GREEN / REFACTOR 0 Подумай 1 Напиши тест 2 Скомпилируй © Luxoft Training 2012 Thursday, December 6, 12
  • 12. RED / GREEN / REFACTOR 0 Подумай 1 Напиши тест 2 Скомпилируй 3 Исправь ошибки © Luxoft Training 2012 Thursday, December 6, 12
  • 13. RED / GREEN / REFACTOR 0 Подумай 1 Напиши тест 2 Скомпилируй 3 Исправь ошибки 4 Запусти и убедись что тесты упали © Luxoft Training 2012 Thursday, December 6, 12
  • 14. RED / GREEN / REFACTOR 0 Подумай 1 Напиши тест 2 Скомпилируй 3 Исправь ошибки 4 Запусти и убедись что тесты упали 5 Напиши код © Luxoft Training 2012 Thursday, December 6, 12
  • 15. RED / GREEN / REFACTOR 0 Подумай 1 Напиши тест 2 Скомпилируй 3 Исправь ошибки 4 Запусти и убедись что тесты упали 5 Напиши код 6 Запусти и убедись что тесты прошли © Luxoft Training 2012 Thursday, December 6, 12
  • 16. RED / GREEN / REFACTOR 0 Подумай 1 Напиши тест 2 Скомпилируй 3 Исправь ошибки 4 Запусти и убедись что тесты упали 5 Напиши код 6 Запусти и убедись что тесты прошли © Luxoft Training 2012 7 Рефакторинг Thursday, December 6, 12
  • 17. RED / GREEN / REFACTOR 0 Подумай 1 Напиши тест 2 Скомпилируй 3 Исправь ошибки Повтори 4 Запусти и убедись что тесты упали 5 Напиши код 6 Запусти и убедись что тесты прошли © Luxoft Training 2012 7 Рефакторинг Thursday, December 6, 12
  • 18. Ошибки TDD Писать тест после кода Писать тест который сразу проходит Писать сразу много тестов © Luxoft Training 2012 Thursday, December 6, 12
  • 19. Инструменты § OCUnit/SenTestingKit начиная IPhone SDK 2.2 § GHUnit § Google Toolkit for Mac § OCMock § OCHamcrest § Kiwi § Cedar § … © Luxoft Training 2012 Thursday, December 6, 12
  • 20. OCUnit § Object-oriented tests § Very low overhead § Tests are in the same language as the implementation § Test case classes cohabit with classes they test § Promotes aggressive refactoring § Helps capture requirements, expose dependencies § Total integration in the development process § Records testing expertise © Luxoft Training 2012 § Tests frameworks, bundles, or applications § Easy installation Thursday, December 6, 12
  • 21. OCUnit Asserts TestCase § STAssertNil § test<Test Case> § STAssertNotNil § setUp § STAssertTrue § tearDown § STAssertFalse § STAssertEquals § STAssertEqualObjects § STFail © Luxoft Training 2012 § ... Thursday, December 6, 12
  • 22. Пример Bowling Game Kata - подсчет очков игры в боулинг www.objectmentor.com wiki.agiledev.ru © Luxoft Training 2012 www.slideshare.net Thursday, December 6, 12
  • 23. © Luxoft Training 2012 Thursday, December 6, 12
  • 24. Правила игры в боулинг Раунды Подсчет очков § 10 раундов (frame-ов) § 10 сразу (strike). Заканчивается досрочно. § В одном  frame – 2 броска 10 очков + pins + pins § Цель – выбить кегли (pins) § 10 очков со второго броска (spare) § Выигрывает набравший больше 10 очков + pins всех очков § Max 300 очков (12 strikes) Последний frame § 1-й strike – дает возможность бросить еще два раза © Luxoft Training 2012 § 2-й spare – дает возможность бросить еще одни раз Thursday, December 6, 12
  • 25. Надо написать BowlingGame + roll(pins : int) + score() : int Написать класс BowlingGame, который имеет два метода • roll (pins : int) – вызывается каждый раз когда игрок бросает шар. Pins – количество выбитых кеглей в этом броске • score() : int – вызывается в конце игры. Показывает результат игры © Luxoft Training 2012 Thursday, December 6, 12
  • 26. A quick design session Нам нужен BowlingGame класс BowlingGame + roll(pins : int) © Luxoft Training 2012 Thursday, December 6, 12
  • 27. A quick design session BowlingGame Frame + roll(pins : int) + score() : int Игра имеет 10 фреймов © Luxoft Training 2012 Thursday, December 6, 12
  • 28. A quick design session BowlingGame Frame Roll + roll(pins : int) + score() : int - pins : int Каждый фрейм состоит из одного или двух бросков © Luxoft Training 2012 Thursday, December 6, 12
  • 29. A quick design session BowlingGame Frame Roll + roll(pins : int) + score() : int - pins : int Tenth Frame Последний фрейм © Luxoft Training 2012 содержит два или три броска Thursday, December 6, 12
  • 30. A quick design session BowlingGame Frame Roll + roll(pins : int) + score() : int - pins : int Score функция должна пройтись по всем фреймам и посчитать результат Tenth Frame © Luxoft Training 2012 Thursday, December 6, 12
  • 31. A quick design session Strike или Spare зависит от количества Next Frame выбитых кеглей в Frame BowlingGame Frame Roll + roll(pins : int) + score() : int - pins : int Tenth Frame © Luxoft Training 2012 Thursday, December 6, 12
  • 32. Готовим среду для тестирования + © Luxoft Training 2012 Thursday, December 6, 12
  • 33. Еще раз повторим правила Раунды Подсчет очков § 10 раундов (frame-ов) § 10 сразу (strike). Заканчивается досрочно. § В одном  frame – 2 броска 10 очков + pins + pins § Цель – выбить кегли (pins) § 10 очков со второго броска (spare) § Выигрывает набравший больше 10 очков + pins всех очков § Max 300 очков (12 strikes) Последний frame § 1-й strike – дает возможность бросить еще два раза © Luxoft Training 2012 § 2-й spare – дает возможность бросить еще одни раз Thursday, December 6, 12
  • 34. Пишем код © Luxoft Training 2012 Thursday, December 6, 12
  • 35. Test List /* should score zero on gutter game Подумай should score twenty when all one should score spare correctly should score all spares correctly should score strike correctly should score super game */ #import "BowlingGameTests.h” @implementation BowlingGameTests - (void)setUp { [super setUp]; } - (void)tearDown { [super tearDown]; © Luxoft Training 2012 } @end Thursday, December 6, 12
  • 36. Assert First - (void)testGutterGame { STAssertEquals(0, [game score], nil); } © Luxoft Training 2012 Thursday, December 6, 12
  • 37. Test First - (void)testGutterGame { BowlingGame *game = [[BowlingGame alloc] init]; for (int i = 0; i < 20; i++) { [game roll:0]; } STAssertEquals(0, [game score], nil); } Пишем тест игнорируя ошибки компилятора © Luxoft Training 2012 Thursday, December 6, 12
  • 38. Исправляем ошибки, пишем код - (void)testGutterGame { BowlingGame *game = [[BowlingGame alloc] init]; for (int i = 0; i < 20; i++) { [game roll:0]; } STAssertEquals(0, [game score], nil); } @implementation BowlingGame - (void)roll:(int)pins { } - (int)score { Пишем минимум return 0; кода! KISS } © Luxoft Training 2012 @end Thursday, December 6, 12
  • 39. Следующий тест - (void)testAllOne Тест падает { BowlingGame *game = [[BowlingGame alloc] init]; for (int i = 0; i < 20; i++) { [game roll:1]; } STAssertEquals(20, [game score], nil); } © Luxoft Training 2012 Thursday, December 6, 12
  • 40. Пишем код - (void)testAllOne { BowlingGame *game = [[BowlingGame alloc] init]; for (int i = 0; i < 20; i++) { [game roll:1]; Тест проходит } STAssertEquals(20, [game score], nil); } #import "BowlingGame.h" @implementation BowlingGame - (void)roll:(int)pins { score += pins; } - (int)score { return score; } © Luxoft Training 2012 @end Thursday, December 6, 12
  • 41. Убираем дублирование - (void)testGutterGame { int n = 20; int pins = 0; for (int i = 0; i < n; i++) { [game roll:pins]; } STAssertEquals(0, [game score], nil); } © Luxoft Training 2012 Thursday, December 6, 12
  • 42. Рефакторим - (void)testGutterGame { [self rollMany:0 times:20]; STAssertEquals(0, [game score], nil); } - (void)testAllOne { [self rollMany:1 times:20]; STAssertEquals(20, [game score], nil); } - (void)rollMany:(int)pins times:(int)n { for (int i = 0; i < n; i++) { [game roll:pins]; } } © Luxoft Training 2012 Thursday, December 6, 12
  • 43. Проверка на Spare 6 3 Тест падает 4 - 10 + 3 3 - (void)testScoreSpare { [game roll:5]; // spare [game roll:5]; [game roll:3]; [self rollMany:17 times:0]; STAssertEquals(16, [game score], nil); } © Luxoft Training 2012 Thursday, December 6, 12
  • 44. Design review #import "BowlingGame.h" roll – занимается подсчетом очков, но @implementation BowlingGame имя метода не указывает на это - (void)roll:(int)pins { score += pins; } - (int)score { return score; } score – не занимается подсчетом @end очков, хотя имя указывает, что должна © Luxoft Training 2012 Thursday, December 6, 12
  • 45. Redesign Добавляем метод в Ignore //- (void)testScoreSpare { // [game roll:5]; // spare // [game roll:5]; // [game roll:3]; // [self rollMany:17 times:0]; // STAssertEquals(16, [game score], nil); //} © Luxoft Training 2012 Thursday, December 6, 12
  • 46. Redesign #import "BowlingGame.h" @implementation BowlingGame - (void)roll:(int)pins { rolls[currentRoll++] = pins; } - (int)score { int score = 0; for (int i = 0; i < 20; i++) score += rolls[i]; return score; } @end © Luxoft Training 2012 Thursday, December 6, 12
  • 47. Убираем Ignore - (void)testScoreSpare { [game roll:5]; // spare [game roll:5]; [game roll:3]; Тест падает [self rollMany:17 times:0]; STAssertEquals(16, [game score], nil); } © Luxoft Training 2012 Thursday, December 6, 12
  • 48. Пишем код - (int)score { int score = 0; for (int i = 0; i < 20; i++) if (rolls[i] + rolls[i + 1] == 10) //spare score += 10 + rolls[i + 2]; ... score += rolls[i]; return score; } Хорошая идея! За одним исключением – это не работает У нас все еще проблемы с дизайном. Очевидно, надо считать очки по фреймам © Luxoft Training 2012 Thursday, December 6, 12
  • 49. Очередная сессия Redesign //- (void)testScoreSpare { // [game roll:5]; // spare // [game roll:5]; // [game roll:3]; // [self rollMany:17 times:0]; // Добавляем метод STAssertEquals(16, [game score], nil); //} в Ignore © Luxoft Training 2012 Thursday, December 6, 12
  • 50. Refactoring - (int)score { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { score += rolls[i] + rolls[i + 1]; i += 2; } return score; } © Luxoft Training 2012 Thursday, December 6, 12
  • 51. Убираем Ignore - (void)testScoreSpare { [game roll:5]; // spare [game roll:5]; Тест падает [game roll:3]; [self rollMany:17 times:0]; STAssertEquals(16, [game score], nil); } © Luxoft Training 2012 Thursday, December 6, 12
  • 52. Пишем код - (int)score { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[i] + rolls[i + 1] == 10) {// spare score += 10 + rolls[i + 2]; i += 2; } else { score += rolls[i] + rolls[i + 1]; i += 2; } } return score; } © Luxoft Training 2012 Thursday, December 6, 12
  • 53. Design review Плохое имя переменной - (int)score { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[i] + rolls[I + 1] == 10) {// spare score += 10 + rolls[i + 2]; i += 2; } Плохо иметь комментарий в else { условии score += rolls[i] + rolls[i + 1]; i += 2; } } return score; } © Luxoft Training 2012 Thursday, December 6, 12
  • 54. Refactoring - (int)score { int score = 0; int ballIndex = 0; for (int frame = 0; frame < 10; frame++) { if ([self isSpare:ballIndex]) { score += 10 + rolls[ballIndex + 2]; ballIndex += 2; } else { score += rolls[ballIndex] + rolls[ballIndex + 1]; ballIndex += 2; } } return score; } - (BOOL)isSpare:(int)ballIndex { © Luxoft Training 2012 return rolls[ballIndex] + rolls[ballIndex+1] == 10; } Thursday, December 6, 12
  • 55. Проверка на Strike 10 3 * 4 10 + 3 + 4 3+4 Комментарий в тесте - (void)testScoreStrike { [game roll:10]; // strike [game roll:3]; [game roll:4]; [self rollMany:16 times:0]; STAssertEquals(24, [game score], nil); } © Luxoft Training 2012 Thursday, December 6, 12
  • 56. Пишем код - (int)score { int score = 0; int ballIndex = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[ballIndex] == 10) { score += 10 + ! ! ! ! ! ! rolls[ballIndex + 1] + ! ! ! ! ! ! ! ! ! rolls[ballIndex + 2]; ballIndex++; } else if ([self isSpare:ballIndex]) { score += 10 + rolls[ballIndex + 2]; ballIndex += 2; } else { score += rolls[ballIndex] + rolls[ballIndex + 1]; ballIndex += 2; } } © Luxoft Training 2012 return score; } Thursday, December 6, 12
  • 57. Design review - (int)score { int score = 0; Комментарий для условия int ballIndex = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[ballIndex] == 10) { // strike score += 10 + rolls[ballIndex + 1] + rolls[ballIndex + 2]; ballIndex++; } else if ([self isSpare:ballIndex]) { score += 10 + rolls[ballIndex + 2]; ballIndex += 2; } else { score += rolls[ballIndex] + rolls[ballIndex + 1]; ballIndex += 2; } } return score; © Luxoft Training 2012 } Непонятное выражение Thursday, December 6, 12
  • 58. Refactoring - (int)score { int score = 0; int ballIndex = 0; for (int frame = 0; frame < 10; frame++) { if ([self isStrike:ballIndex]) { score += 10 + [self strikeBonus:ballIndex]; ballIndex++; } else if ([self isSpare:ballIndex]) { score += 10 + [self spareBonus:ballIndex]; ballIndex += 2; } else { score += [self sumOfBallsInFrame:ballIndex]; ballIndex += 2; } } return score; } © Luxoft Training 2012 Thursday, December 6, 12
  • 59. Refactoring - (void)testScoreStrike { [self rollStrike]; [game roll:3]; [game roll:4]; [self rollMany:16 times:0]; STAssertEquals(24, [game score], nil); } - (void)rollStrike { [game roll:10]; } © Luxoft Training 2012 git checkout bowling-0.8 Thursday, December 6, 12
  • 60. Контрольный пример - (void)testPrefectGame { [self rollMany:10 times:12]; STAssertEquals(300, [game score], nil); } © Luxoft Training 2012 Thursday, December 6, 12
  • 61. Cтратегии запуска тестов § IDE § Console § CocoaPods § Maven § Test Runner § CI § File watcher © Luxoft Training 2012 Thursday, December 6, 12
  • 62. Continuous integration Hudson Team City © Luxoft Training 2012 Thursday, December 6, 12
  • 63. Преимущества от TDD Меньше ошибок Проще рефакторить Документация Лучший дизайн кода Быстрее процесс разработки © Luxoft Training 2012 Thursday, December 6, 12
  • 64. BDD Behavior Driven Development (BDD) © Luxoft Training 2012 Thursday, December 6, 12
  • 65. BDD – что это? Language © Luxoft Training 2012 Thursday, December 6, 12
  • 66. Difference between TDD, BDD & ATDD TDD ATDD © Luxoft Training 2012 Thursday, December 6, 12
  • 67. BDD DDD-Domain Driven Testing + DSL + GIVEN / WHEN / THEN Спецификация Тесты Документация © Luxoft Training 2012 Thursday, December 6, 12
  • 68. Kiwi describe(@"BowlingGame", ^{ it(@"should score zero on gutter game", ^{ rollMany(20, 0); [[theValue([game score]) should] equal:theValue(0)]; }); it(@"should score twenty when all one", ^{ rollMany(20, 1); [[theValue([game score]) should] equal:theValue(20)]; }); it(@"should score spare correctly", ^{ [game roll:5]; [game roll:5]; [game roll:3]; rollMany(17, 0); [[theValue([game score]) should] equal:theValue(16)]; }); it(@"should score strike correctly", ^{ [game roll:10]; [game roll:3]; © Luxoft Training 2012 [game roll:4]; rollMany(16, 0); [[theValue([game score]) should] equal:theValue(24)]; }); Thursday, December 6, 12
  • 69. © Luxoft Training 2012 Thursday, December 6, 12
  • 70. © Luxoft Training 2012 Thursday, December 6, 12
  • 71. *.feature # language: ru Функционал: Авторизация пользователей Чтобы указывать себя автором снипетов, голосовать за снипеты и нарабатывать карму, пользователи должны иметь возможность регистрироваться Сценарий: Успешная авторизация с указываемыми логином и паролем Допустим я зарегистрированный пользователь "User12" с паролем "User1212" И я на странице Авторизация Если ввожу в поле Логин "User12" И ввожу в поле Пароль "User1212" И кликаю кнопку "Войти" То я должен увидеть уведомление "Добро пожаловать!" И я должен оказаться на странице Страница пользователя © Luxoft Training 2012 Thursday, December 6, 12
  • 72. *.feature © Luxoft Training 2012 Thursday, December 6, 12
  • 73. Вопросы ? © Luxoft Training 2012 Thursday, December 6, 12
  • 74. Разработка через тестирование IDyachenko@luxoft.com git clone git://github.com/ivan-dyachenko/Trainings.git © Luxoft Training 2012 https://github.com/ivan-dyachenko/Trainings Thursday, December 6, 12