2013-01-10 iOS testing


Published on

Published in: Technology, Education
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

2013-01-10 iOS testing

  1. 1. Testing in iOS10.01.2013 by Tomasz Janeczko
  2. 2. About meTomasz Janeczko• iOS developer in Kainos• Enthusiast of business, electronics, Rails& Heroku• Organizer of first App Camp in UK andPL
  3. 3. So let’s talk about testing.
  4. 4. Why we test?
  5. 5. So?
  6. 6. • Reliability• Regression• Confidence (e.g. refactoring)
  7. 7. Why not to test?
  8. 8. Why not to test?• Heavy dependence on UI• Non-testable code• Bad framework
  9. 9. How to address issues• Sample - downloading stuff frominterwebz
  10. 10. First faultWriting tests afterwriting code
  11. 11. Separation of concerns
  12. 12. Separation of concerns• Let’s separate out the UI code• Same for services interaction
  13. 13. Demo of tests
  14. 14. Writing testsMeet Kiwi and OCMock
  15. 15. Kiwi• RSpec-like tests writing• Matchers• Cleaner and more self-descriptive code
  16. 16. Kiwidescribe(@"Tested class", ^{context(@"When created", ^{it(@"should not fail", ^{[[theValue(0) should] equal:theValue(0)];});});});
  17. 17. Kiwidescribe(@"Tested class", ^{context(@"When created", ^{it(@"should not fail", ^{id viewController = [ViewController new];[[viewController should]conformToProtocol:@protocol(UITableViewDelegate)];});});});
  18. 18. Matchers[subject  shouldNotBeNil]• [subject  shouldBeNil]• [[subject  should]  beIdenticalTo:(id)anObject] - compares ids• [[subject  should]  equal:(id)anObject]• [[subject  should]  equal:(double)aValue  withDelta:(double)aDelta]• [[subject  should]  beWithin:(id)aDistance  of:(id)aValue]• [[subject  should]  beLessThan:(id)aValue]• etc.  etc.
  19. 19. Compare to SenTesting Kit[[subject  should]  equal:anObject]compare  withSTAssertEquals(subject,  anObject,  @”Should  be  equal”);
  20. 20. OCMock• Mocking and stubbing library for iOS• Quite versatile• Makes use of NSProxy magic
  21. 21. Sample workflows
  22. 22. Classic calculator sampledescribe(@"Calculator",  ^{                context(@"with  the  numbers  60  and  5  entered",  ^{                RPNCalculator  *calculator  =  [[RPNCalculator  alloc]  init];                                beforeEach(^{                        [calculator  enter:60];                        [calculator  enter:5];                });                afterEach(^{                          [calculator  clear];                });                              it(@"returns  65  as  the  sum",  ^{                        [[theValue([calculator  add])  should]  equal:65  withDelta:.01];                });
  23. 23. Test if calls dep methods1. Create a mock dependency2. Inject it3. Call the method4. Verify
  24. 24. Test dependency// Create the tested object and mock to exchange part of the functionalityviewController = [ViewController new];mockController = [OCMockObject partialMockForObject:viewController];// Create the mock and change implementation to return our classid serviceMock = [OCMockObject mockForClass:[InterwebzService class]];[[[mockController stub] andReturn:serviceMock] service];// Define expectations[[serviceMock expect] downloadTweetsJSONWithSuccessBlock:[OCMArg any]];// Run the tested method[viewController tweetsButtonTapped:nil];// Verify - throws exception on failure[mockController verify];
  25. 25. Testing one layer• Isolate dependencies• Objective-C is highly dynamic - we canchange implementations of privatemethods or static methods• We can avoid IoC containers for testing
  26. 26. Accessing private methods
  27. 27. Accessing private methods@interface ViewController()- (void)startDownloadingTweets;@end...[[mockController expect] startDownloadingTweets];
  28. 28. Static method testing• Through separation to a method@interface ViewController()- (NSUserDefaults *)userDefaults;@end...id mockDefaults = [OCMockObject mockForClass:[NSUserDefaults class]];[[[mockDefaults expect] andReturn:@"Setting"] valueForKey:[OCMArg any]];[[[mockController stub] andReturn:mockDefaults] userDefaults];
  29. 29. Static method testing• Through method swizzlingvoid  SwizzleClassMethod(Class  c,  SEL  orig,  SEL  new)  {        Method  origMethod  =  class_getClassMethod(c,  orig);        Method  newMethod  =  class_getClassMethod(c,  new);        c  =  object_getClass((id)c);        if(class_addMethod(c,  orig,  method_getImplementation(newMethod),  method_getTypeEncoding(newMethod)))                class_replaceMethod(c,  new,  method_getImplementation(origMethod),  method_getTypeEncoding(origMethod));        else                method_exchangeImplementations(origMethod,  newMethod);}
  30. 30. Normal conditions applydespite it’s iOS & Objective--C
  31. 31. Problems of „mobile devs”• Pushing code with failing tests• Lot’s of hacking together• Weak knowledge of VCS tools - mergenightmares
  32. 32. Ending thoughts• Think first (twice), then code :)• Tests should come first• Write the failing test, pass the test,refactor• Adequate tools can enhance yourtesting experience
  33. 33. Ending thoughts• Practice!
  34. 34. Thanks!
  35. 35. Questions