Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
TAKING A TEST DRIVE: USING TDD TO WRITE AN IOS APP    Graham Lee, professional in-betweener                 @iamleeg
TESTING: GOALS                              Cost                          Time Detected• validate   code behaviour        ...
TESTING: GOALS                              Cost                          Time Detected• validate   code behaviour        ...
THE TESTING LANDSCAPE                                                         System Test Beta/Acceptance TestingBlack Box...
THE TESTING LANDSCAPE                                                         System Test Beta/Acceptance TestingBlack Box...
TDD - WHAT IT ACHIEVES• Imposes    black-box thinking for the developer• Guides    design and implementation• YAGNI• Provi...
FIND BUGS BEFORE…
…YOUR CUSTOMERS DO                © 2009 Microsoft
TDD != [BULLET                  SILVERCOLOR]• Can’t   ensure the developer understood requirements• Or   that the requirem...
HOW TDD WORKS
HOW TDD WORKS     RED
HOW TDD WORKS     RED    GREEN
HOW TDD WORKS     RED    GREEN   REFACTOR
HOW TDD WORKS           RED Well, maybe a bit of brown...         GREEN      REFACTOR
TEST DESIGN- (void)setUp {   gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];   c...
TESTABLE CODE
TESTABLE CODE• Small, focussed   classes, that contain…
TESTABLE CODE• Small, focussed   classes, that contain…• Short   methods, each with obvious effect
TESTABLE CODE• Small, focussed   classes, that contain…• Short   methods, each with obvious effect• Any   side-effects are...
TESTABLE CODE• Small, focussed   classes, that contain…• Short   methods, each with obvious effect• Any   side-effects are...
TESTABLE CODE• Small, focussed   classes, that contain…• Short   methods, each with obvious effect• Any   side-effects are...
DESIGN CONSEQUENCES
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
CLASSES DO NOT LIVE IN      ISOLATION
ViewController Model     CLASSES DO NOT LIVE IN           ISOLATION
FAKE OBJECTS• For   when state is important• Remove “internal” complexity• Provide     non-standard visibility• Keeptrack ...
FAKE OBJECTS• For   when state is important• Remove “internal” complexity• Provide     non-standard visibility• Keeptrack ...
FAKE OBJECTS     A protocol                                   works well here• For   when state is important• Remove “inte...
HERE’S A FAKE OBJECT@interface FakeNotificationCenter : NSObject {  NSMutableDictionary *dictionary;}- (void)addObserver: ...
HERE’S A FAKE OBJECT@implementation FakeNotificationCenter- (id)init {   self = [super init];   if (self) {       dictiona...
…AND HERE’S THE TEST…- (void)testStoreSubscribesToLowMemoryNotification {   [store registerForMemoryWarnings: (NSNotificat...
…AND THE CODE- (void)registerForMemoryWarnings:(NSNotificationCenter *)center {   [center addObserver: self selector: @sel...
MOCK OBJECTS• For    when behaviour is important• Recordwhat messages with what parameters are expected• Verify   that thi...
MOCK OBJECTS• For    when behaviour is important• Recordwhat messages with what parameters are expected• Verify   that thi...
HERE’S (THE SAME) TEST- (void)testStoreRegistersForMemoryWarnings{   id center = [OCMockObject mockForClass: [NSNotificati...
CONCLUSIONS• Test-driven   development helps understand and improve code quality• …but     it’s mainly a design thing• TDD...
QUESTIONS?
Prochain SlideShare
Chargement dans…5
×

Taking a Test Drive: iOS Dev UK guide to TDD

2 257 vues

Publié le

Presentation given at iOS Dev UK, Aberystwyth, in September 2011 on the benefits of test-driven development.

Publié dans : Technologie

Taking a Test Drive: iOS Dev UK guide to TDD

  1. 1. TAKING A TEST DRIVE: USING TDD TO WRITE AN IOS APP Graham Lee, professional in-betweener @iamleeg
  2. 2. TESTING: GOALS Cost Time Detected• validate code behaviour Time Requirements Architecture Construction System After introduced Test Release• discover defects Requirements 1 3 5-10 10 10-100• verify fixes Architecture - 1 10 15 25-100• detect regressions Construction - - 1 10 10-25
  3. 3. TESTING: GOALS Cost Time Detected• validate code behaviour Time Requirements Architecture Construction System After introduced Test Release• discover defects Requirements 1 3 5-10 10 10-100• verify fixes Architecture - 1 10 15 25-100• detect regressions Construction - - 1 10 10-25 Unit Testing
  4. 4. THE TESTING LANDSCAPE System Test Beta/Acceptance TestingBlack Box Pen/fuzz Testing Integration Testing GUI TestingGrey Box Unit testing (undirected) Source AuditWhite Box Class Component System Static Analysis, Debugging
  5. 5. THE TESTING LANDSCAPE System Test Beta/Acceptance TestingBlack Box Pen/fuzz Testing Integration Testing GUI Testing TDDGrey Box Unit testing (undirected) Source AuditWhite Box Class Component System Static Analysis, Debugging
  6. 6. TDD - WHAT IT ACHIEVES• Imposes black-box thinking for the developer• Guides design and implementation• YAGNI• Provides a safety net for future development• Assists accurate planning
  7. 7. FIND BUGS BEFORE…
  8. 8. …YOUR CUSTOMERS DO © 2009 Microsoft
  9. 9. TDD != [BULLET SILVERCOLOR]• Can’t ensure the developer understood requirements• Or that the requirements remained static• Doesn’t guarantee successful integration• Takes time
  10. 10. HOW TDD WORKS
  11. 11. HOW TDD WORKS RED
  12. 12. HOW TDD WORKS RED GREEN
  13. 13. HOW TDD WORKS RED GREEN REFACTOR
  14. 14. HOW TDD WORKS RED Well, maybe a bit of brown... GREEN REFACTOR
  15. 15. TEST DESIGN- (void)setUp { gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar]; comps = [[NSDateComponents alloc] init];} Common stuff here- (void)tearDown { [gregorianCalendar release]; gregorianCalendar = nil; [comps release]; comps = nil;}- (void)testDatesOnTheSameDayAreConsideredSame { //...}- (void)testCloseDatesOnSeparateDaysAreNotSame {} //... These all independent- (void)testSameDayInDifferentYearsAreNotTheSame {} //... short, readable, fast
  16. 16. TESTABLE CODE
  17. 17. TESTABLE CODE• Small, focussed classes, that contain…
  18. 18. TESTABLE CODE• Small, focussed classes, that contain…• Short methods, each with obvious effect
  19. 19. TESTABLE CODE• Small, focussed classes, that contain…• Short methods, each with obvious effect• Any side-effects are few and easy to predict
  20. 20. TESTABLE CODE• Small, focussed classes, that contain…• Short methods, each with obvious effect• Any side-effects are few and easy to predict• Helper data passed in, not discovered
  21. 21. TESTABLE CODE• Small, focussed classes, that contain…• Short methods, each with obvious effect• Any side-effects are few and easy to predict• Helper data passed in, not discovered• Low “cyclomatic complexity”
  22. 22. DESIGN CONSEQUENCES
  23. 23. CLASSES DO NOT LIVE IN ISOLATION
  24. 24. CLASSES DO NOT LIVE IN ISOLATION
  25. 25. CLASSES DO NOT LIVE IN ISOLATION
  26. 26. CLASSES DO NOT LIVE IN ISOLATION
  27. 27. CLASSES DO NOT LIVE IN ISOLATION
  28. 28. CLASSES DO NOT LIVE IN ISOLATION
  29. 29. CLASSES DO NOT LIVE IN ISOLATION
  30. 30. CLASSES DO NOT LIVE IN ISOLATION
  31. 31. CLASSES DO NOT LIVE IN ISOLATION
  32. 32. CLASSES DO NOT LIVE IN ISOLATION
  33. 33. ViewController Model CLASSES DO NOT LIVE IN ISOLATION
  34. 34. FAKE OBJECTS• For when state is important• Remove “internal” complexity• Provide non-standard visibility• Keeptrack of changes made from outside• Examples: Core Data, network, filesystem
  35. 35. FAKE OBJECTS• For when state is important• Remove “internal” complexity• Provide non-standard visibility• Keeptrack of changes made from outside• Examples: Core Data, network, filesystem
  36. 36. FAKE OBJECTS A protocol works well here• For when state is important• Remove “internal” complexity• Provide non-standard visibility• Keeptrack of changes made from outside• Examples: Core Data, network, filesystem
  37. 37. HERE’S A FAKE OBJECT@interface FakeNotificationCenter : NSObject { NSMutableDictionary *dictionary;}- (void)addObserver: (id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;- (void)removeObserver: (id)observer;- (BOOL)hasObject: (id)observer forNotification: (NSString *)aName;@end
  38. 38. HERE’S A FAKE OBJECT@implementation FakeNotificationCenter- (id)init { self = [super init]; if (self) { dictionary = [[NSMutableDictionary alloc] init]; } return self;}- (void)addObserver: (id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject { [dictionary setObject: observer forKey: aName];}- (void)removeObserver:(id)observer { [[dictionary copy] enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { if ([obj isEqual: observer]) { [dictionary removeObjectForKey: key]; } }];}- (BOOL)hasObject:(id)observer forNotification:(NSString *)aName { return [[dictionary objectForKey: aName] isEqual: observer];}@end
  39. 39. …AND HERE’S THE TEST…- (void)testStoreSubscribesToLowMemoryNotification { [store registerForMemoryWarnings: (NSNotificationCenter *)center]; STAssertTrue([center hasObject: store forNotification: UIApplicationDidReceiveMemoryWarningNotification], @"store should haveregistered for the notification");}
  40. 40. …AND THE CODE- (void)registerForMemoryWarnings:(NSNotificationCenter *)center { [center addObserver: self selector: @selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object: nil];}
  41. 41. MOCK OBJECTS• For when behaviour is important• Recordwhat messages with what parameters are expected• Verify that this expectation is met
  42. 42. MOCK OBJECTS• For when behaviour is important• Recordwhat messages with what parameters are expected• Verify that this expectation is met
  43. 43. HERE’S (THE SAME) TEST- (void)testStoreRegistersForMemoryWarnings{ id center = [OCMockObject mockForClass: [NSNotificationCenter class]]; [[center expect] addObserver: store selector: [OCMArg anyPointer] name:UIApplicationDidReceiveMemoryWarningNotification object: [OCMArg any]]; [store registerForMemoryWarnings: center]; [center verify];}
  44. 44. CONCLUSIONS• Test-driven development helps understand and improve code quality• …but it’s mainly a design thing• TDD code has a tendency towards small, independent, reusable modules of size ~1 class
  45. 45. QUESTIONS?

×