Tdd iPhone For Dummies

3,826 views
3,645 views

Published on

Everything you must know to start develop iPhone Applications in safe and fun way!

Published in: Technology
3 Comments
8 Likes
Statistics
Notes
  • really interesting and useful
    the images used in the presentation are very funny
    thank you!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Grazie mille!
    Ho cercato di essere leggero e stuzzicare la curiosità in modo da approfondire un tema molto importante.
    Sono felice che entrambi gli scopi siano stati raggiunti :-)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Ottima presentazione. Complimenti anche per l'esposizione fluida e per niente noisa.
    Lo speech ha sicuramente stuzzicato la mia attenzione con spunti di riflessione davvero interessanti, c'è molto da crescere nell'ambito TDD per Objective-c e a maggior ragione per iPhone.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
3,826
On SlideShare
0
From Embeds
0
Number of Embeds
63
Actions
Shares
0
Downloads
75
Comments
3
Likes
8
Embeds 0
No embeds

No notes for slide

Tdd iPhone For Dummies

  1. 1. Does it work?
  2. 2. I’m not here to convince you
  3. 3. Dry and easy to maintain
  4. 4. Better form of documentation
  5. 5. Protect
  6. 6. Tdd?
  7. 7. Tdd? Test-driven development (TDD) is a software development technique that relies on the repetition of a very short development cycle http://en.wikipedia.org/wiki/Test-driven_development
  8. 8. Tdd? first the developer writes a failing automated test case that defines a desired improvement or new function http://en.wikipedia.org/wiki/Test-driven_development
  9. 9. Tdd? then produces code to pass that test http://en.wikipedia.org/wiki/Test-driven_development
  10. 10. Tdd? and finally refactors the new code to acceptable standard http://en.wikipedia.org/wiki/Test-driven_development
  11. 11. Unit Tests? A test is not a unit test if: Michael Feathers
  12. 12. Unit Tests? It talks to a database Michael Feathers
  13. 13. Unit Tests? It communicates across the network Michael Feathers
  14. 14. Unit Tests? It touches the file system Michael Feathers
  15. 15. Unit Tests? You have to do things to your environment to run it (eg, change config files) Michael Feathers
  16. 16. Unit Tests? Tests that do this are integration tests Michael Feathers
  17. 17. Automatic Testing Lifecycle Steps Fixture Setup
  18. 18. Automatic Testing Lifecycle Steps Fixture Setup SUT Exercise SUT
  19. 19. Automatic Testing Lifecycle Steps Fixture Setup SUT Exercise SUT Verify Result
  20. 20. Automatic Testing Lifecycle Steps Fixture Setup Exercise SUT Verify Result Fixture TearDown
  21. 21. What about iPhone Dev?
  22. 22. Unit Testing for iPhone
  23. 23. Former SenTestingKit OCUnit
  24. 24. TestCase definition #import <SenTestingKit/SenTestingKit.h> #import "RpnCalculator.h" @interface RpnCalculatorTestCase : SenTestCase { ! RpnCalculator* rpnCalculator; } @end
  25. 25. TestCase definition #import <SenTestingKit/SenTestingKit.h> #import "RpnCalculator.h" @interface RpnCalculatorTestCase : SenTestCase { ! RpnCalculator* rpnCalculator; } @end
  26. 26. TestCase Implementation @implementation RpnCalculatorTestCase -(void)setUp{ ! rpnCalculator = [[RpnCalculator alloc]init]; } -(void)testShouldDisplayTwoNumbersWhenNumbersAreSeparatedByEnter{ ! [rpnCalculator put:@"1"]; ! [rpnCalculator put:@"enter"]; ! [rpnCalculator put:@"2"];! ! ! STAssertEqualObjects(@"1n2",rpnCalculator.display,nil); } -(void)tearDown{ [rpnCalculator release]; }
  27. 27. Fixture Setup @implementation RpnCalculatorTestCase -(void)setUp{ ! rpnCalculator = [[RpnCalculator alloc]init]; } -(void)testShouldDisplayTwoNumbersWhenNumbersAreSeparatedByEnter{ ! [rpnCalculator put:@"1"]; ! [rpnCalculator put:@"enter"]; ! [rpnCalculator put:@"2"];! ! ! STAssertEqualObjects(@"1n2",rpnCalculator.display,nil); } -(void)tearDown{ [rpnCalculator release]; }
  28. 28. Exercise SUT @implementation RpnCalculatorTestCase -(void)setUp{ ! rpnCalculator = [[RpnCalculator alloc]init]; } -(void)testShouldDisplayTwoNumbersWhenNumbersAreSeparatedByEnter{ ! [rpnCalculator put:@"1"]; ! [rpnCalculator put:@"enter"]; ! [rpnCalculator put:@"2"];! ! ! STAssertEqualObjects(@"1n2",rpnCalculator.display,nil); } -(void)tearDown{ [rpnCalculator release]; }
  29. 29. Verify Result @implementation RpnCalculatorTestCase -(void)setUp{ ! rpnCalculator = [[RpnCalculator alloc]init]; } -(void)testShouldDisplayTwoNumbersWhenNumbersAreSeparatedByEnter{ ! [rpnCalculator put:@"1"]; ! [rpnCalculator put:@"enter"]; ! [rpnCalculator put:@"2"];! ! ! STAssertEqualObjects(@"1n2",rpnCalculator.display,nil); } -(void)tearDown{ [rpnCalculator release]; }
  30. 30. Fixture Teardown @implementation RpnCalculatorTestCase -(void)setUp{ ! rpnCalculator = [[RpnCalculator alloc]init]; } -(void)testShouldDisplayTwoNumbersWhenNumbersAreSeparatedByEnter{ ! [rpnCalculator put:@"1"]; ! [rpnCalculator put:@"enter"]; ! [rpnCalculator put:@"2"];! ! ! STAssertEqualObjects(@"1n2",rpnCalculator.display,nil); } -(void)tearDown{ [rpnCalculator release]; }
  31. 31. Assertions #define STAssertNil(a1, description, ...) #define STAssertNotNil(a1, description, ...) #define STAssertTrue(expression, description, ...) #define STAssertFalse(expression, description, ...) #define STAssertEqualObjects(a1, a2, description, ...) #define STAssertEquals(a1, a2, description, ...) #define STFail(description, ...) #define STAssertTrueNoThrow(expression, description, ...) #define STAssertFalseNoThrow(expression, description, ...) //....
  32. 32. Xcode integration
  33. 33. Xcode integration
  34. 34. Presentation separate from logic
  35. 35. Presentation separate from logic
  36. 36. Presentation
  37. 37. Logic
  38. 38. Test
  39. 39. Xcode integration
  40. 40. Xcode integration
  41. 41. What if I have to access network...
  42. 42. Or I have correlated components..
  43. 43. Mock it!
  44. 44. Mock it! [...] mock objects are simulated objects that mimic the behavior of real objects in controlled ways
  45. 45. OCMock http://www.mulle-kybernetik.com/software/OCMock/
  46. 46. Stubs vs Mocks Mocks Stubs
  47. 47. Stub - (void)testReturnsStubbedReturnValue { ! mock = [OCMockObject mockForClass:[NSString class]]; [[[mock stub] andReturn:@"megamock"] lowercaseString]; id returnValue = [mock lowercaseString]; ! STAssertEqualObjects(@"megamock", returnValue, nil); }
  48. 48. Collaboration SOAPMessage XMLString SOAPClient send SOAPChannel post
  49. 49. Collaboration SOAPMessage XMLString SOAPClient send SOAPChannel post
  50. 50. Collaboration SOAPMessage XMLString SOAPClient send SOAPChannel post
  51. 51. Mock static const NSString * RawSOAPMessage = @"<ENV:evn xmlns:ENV="http://www.w3.org/.... - (void)testClientShouldSendMessage{ ! id msgMock = [OCMockObject mockForClass:[SOAPMessage class]]; ! [[[msgMock expect] andReturn:RawSOAPMessage] XMLString]; ! id channelMock = [OCMockObject mockForClass:[SOAPChannel class]]; ! [[[channelMock expect] andReturn:TRUE] send]; ! SOAPClient *client = [SOAPClient initWith:channelMock]; ! ! [client sendMessage:msgMock]; ! [msgMock verify]; ! [channelMock verify]; }
  52. 52. Mockery static const NSString * RawSOAPMessage = @"<ENV:evn xmlns:ENV="http://www.w3.org/.... - (void)testClientShouldSendMessage{ ! id msgMock = [OCMockObject mockForClass:[SOAPMessage class]]; ! [[[msgMock expect] andReturn:RawSOAPMessage] XMLString]; ! id channelMock = [OCMockObject mockForClass:[SOAPChannel class]]; ! [[[channelMock expect] andReturn:TRUE] send]; ! SOAPClient *client = [SOAPClient initWith:channelMock]; ! ! [client sendMessage:msgMock]; ! [msgMock verify]; ! [channelMock verify]; }
  53. 53. Exercise SUT static const NSString * RawSOAPMessage = @"<ENV:evn xmlns:ENV="http://www.w3.org/.... - (void)testClientShouldSendMessage{ ! id msgMock = [OCMockObject mockForClass:[SOAPMessage class]]; ! [[[msgMock expect] andReturn:RawSOAPMessage] XMLString]; ! id channelMock = [OCMockObject mockForClass:[SOAPChannel class]]; ! [[[channelMock expect] andReturn:TRUE] send]; ! SOAPClient *client = [SOAPClient initWith:channelMock]; ! ! [client sendMessage:msgMock]; ! [msgMock verify]; ! [channelMock verify]; }
  54. 54. Verify static const NSString * RawSOAPMessage = @"<ENV:evn xmlns:ENV="http://www.w3.org/.... - (void)testClientShouldSendMessage{ ! id msgMock = [OCMockObject mockForClass:[SOAPMessage class]]; ! [[[msgMock expect] andReturn:RawSOAPMessage] XMLString]; ! id channelMock = [OCMockObject mockForClass:[SOAPChannel class]]; ! [[[channelMock expect] andReturn:TRUE] send]; ! SOAPClient *client = [SOAPClient initWith:channelMock]; ! ! [client sendMessage:msgMock]; ! [msgMock verify]; ! [channelMock verify]; }
  55. 55. What’s wrong with Unit Testing?
  56. 56. TEST
  57. 57. Tdd isn’t about tests, but about behaviors and specifications
  58. 58. A spoonful of syntactic sugar...
  59. 59. A spoonful of syntactic sugar... Behavior Driven Development
  60. 60. should insted of test matchers instead of Assert
  61. 61. Bdd framework for iPhone Dev...
  62. 62. Bdd framework for iPhone Dev...
  63. 63. Spec Example -(void)before { ! [SpecHelper loginAsAdmin]; } -(void)itShouldAddAUser { ! [app.navigationButton touch]; ! [[app.textField.with placeholder:@"First Name"] setText:@"Brian"]; ! [[app.textField.with placeholder:@"Last Name"] setText:@"Knorr"]; ! [[app.textField.with placeholder:@"Email"] setText:@"b@g.com"]; ! [[app.textField placeholder:@"Username"] setText:@"bkuser"]; ! [[app.textField placeholder:@"Password"] setText:@"test"]; ! [[app.textField placeholder:@"Confirm"] setText:@"test"]; ! [[app.navigationButton.label text:@"Save"] touch]; ! [app timeout:1].alertView.should.not.exist; ! [[app.tableView.label text:@"Brian Knorr"] should].exist; } -(void)after { ! [SpecHelper logout]; }
  64. 64. Fixture Setup -(void)before { ! [SpecHelper loginAsAdmin]; } -(void)itShouldAddAUser { ! [app.navigationButton touch]; ! [[app.textField.with placeholder:@"First Name"] setText:@"Brian"]; ! [[app.textField.with placeholder:@"Last Name"] setText:@"Knorr"]; ! [[app.textField.with placeholder:@"Email"] setText:@"b@g.com"]; ! [[app.textField placeholder:@"Username"] setText:@"bkuser"]; ! [[app.textField placeholder:@"Password"] setText:@"test"]; ! [[app.textField placeholder:@"Confirm"] setText:@"test"]; ! [[app.navigationButton.label text:@"Save"] touch]; ! [app timeout:1].alertView.should.not.exist; ! [[app.tableView.label text:@"Brian Knorr"] should].exist; } -(void)after { ! [SpecHelper logout]; }
  65. 65. Exercise SUT -(void)before { ! [SpecHelper loginAsAdmin]; } -(void)itShouldAddAUser { ! [app.navigationButton touch]; ! [[app.textField.with placeholder:@"First Name"] setText:@"Brian"]; ! [[app.textField.with placeholder:@"Last Name"] setText:@"Knorr"]; ! [[app.textField.with placeholder:@"Email"] setText:@"b@g.com"]; ! [[app.textField placeholder:@"Username"] setText:@"bkuser"]; ! [[app.textField placeholder:@"Password"] setText:@"test"]; ! [[app.textField placeholder:@"Confirm"] setText:@"test"]; ! [[app.navigationButton.label text:@"Save"] touch]; ! [app timeout:1].alertView.should.not.exist; ! [[app.tableView.label text:@"Brian Knorr"] should].exist; } -(void)after { ! [SpecHelper logout]; }
  66. 66. Verify Result -(void)before { ! [SpecHelper loginAsAdmin]; } -(void)itShouldAddAUser { ! [app.navigationButton touch]; ! [[app.textField.with placeholder:@"First Name"] setText:@"Brian"]; ! [[app.textField.with placeholder:@"Last Name"] setText:@"Knorr"]; ! [[app.textField.with placeholder:@"Email"] setText:@"b@g.com"]; ! [[app.textField placeholder:@"Username"] setText:@"bkuser"]; ! [[app.textField placeholder:@"Password"] setText:@"test"]; ! [[app.textField placeholder:@"Confirm"] setText:@"test"]; ! [[app.navigationButton.label text:@"Save"] touch]; ! [app timeout:1].alertView.should.not.exist; ! [[app.tableView.label text:@"Brian Knorr"] should].exist; } -(void)after { ! [SpecHelper logout]; }
  67. 67. Fixture Teardown -(void)before { ! [SpecHelper loginAsAdmin]; } -(void)itShouldAddAUser { ! [app.navigationButton touch]; ! [[app.textField.with placeholder:@"First Name"] setText:@"Brian"]; ! [[app.textField.with placeholder:@"Last Name"] setText:@"Knorr"]; ! [[app.textField.with placeholder:@"Email"] setText:@"b@g.com"]; ! [[app.textField placeholder:@"Username"] setText:@"bkuser"]; ! [[app.textField placeholder:@"Password"] setText:@"test"]; ! [[app.textField placeholder:@"Confirm"] setText:@"test"]; ! [[app.navigationButton.label text:@"Save"] touch]; ! [app timeout:1].alertView.should.not.exist; ! [[app.tableView.label text:@"Brian Knorr"] should].exist; } -(void)after { ! [SpecHelper logout]; }
  68. 68. Run On Simulator
  69. 69. No XCode Integration Yet
  70. 70. Conclusions
  71. 71. The Market Asks For Apps
  72. 72. More Apps...
  73. 73. More Apps...
  74. 74. More Apps!
  75. 75. Lot to Improve
  76. 76. Be Good Kids:
  77. 77. Test First!
  78. 78. Reclame http://milano-xpug.pbworks.com/ http://tech.groups.yahoo.com/group/milano-xpug/
  79. 79. Questions?

×