Testing in iOS10.01.2013 by Tomasz Janeczko
About meTomasz Janeczko• iOS developer in Kainos• Enthusiast of business, electronics, Rails  & Heroku• Organizer of first ...
So let’s talk about testing.
Why we test?
So?
• Reliability• Regression• Confidence (e.g. refactoring)
Why not to test?
Why not to test?• Heavy dependence on UI• Non-testable code• Bad framework
How to address issues• Sample - downloading stuff from  interwebz
First faultWriting tests afterwriting code
Separation of concerns
Separation of concerns• Let’s separate out the UI code• Same for services interaction
Demo of tests
Writing testsMeet Kiwi and OCMock
Kiwi• RSpec-like tests writing• Matchers• Cleaner and more self-descriptive code
Kiwi  describe(@"Tested class", ^{      context(@"When created", ^{            it(@"should not fail", ^{                [[...
Kiwidescribe(@"Tested class", ^{      context(@"When created", ^{        it(@"should not fail", ^{            id viewContr...
Matchers  [subject	  shouldNotBeNil]• [subject	  shouldBeNil]• [[subject	  should]	  beIdenticalTo:(id)anObject] - compare...
Compare to SenTesting Kit               [[subject	  should]	  equal:anObject]                            compare	  with   ...
OCMock• Mocking and stubbing library for iOS• Quite versatile• Makes use of NSProxy magic
Sample workflows
Classic calculator sample                describe(@"Calculator",	  ^{	  	  	  	   	  	  	  	  context(@"with	  the	  numbe...
Test if calls dep methods 1. Create a mock dependency 2. Inject it 3. Call the method 4. Verify
Test dependency// Create the tested object and mock to exchange part of the functionalityviewController = [ViewController ...
Testing one layer• Isolate dependencies• Objective-C is highly dynamic - we can  change implementations of private  method...
Accessing private methods
Accessing private methods @interface ViewController() - (void)startDownloadingTweets; @end ... [[mockController expect] st...
Static method testing• Through separation to a method@interface ViewController()- (NSUserDefaults *)userDefaults;@end...id...
Static method testing• Through method swizzlingvoid	  SwizzleClassMethod(Class	  c,	  SEL	  orig,	  SEL	  new)	  {	  	  	 ...
Normal conditions apply   despite it’s iOS & Objective--C
Problems of „mobile devs” • Pushing code with failing tests • Lot’s of hacking together • Weak knowledge of VCS tools - me...
Ending thoughts• Think first (twice), then code :)• Tests should come first• Write the failing test, pass the test,  refacto...
Ending thoughts• Practice!
Thanks!
Questions
iOS testing
Upcoming SlideShare
Loading in …5
×

iOS testing

1,601 views

Published on

Testing in iOS using Kiwi and OCMock frameworks

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,601
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
16
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide

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 and PL
  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 from interwebz
  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. Kiwi describe(@"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  with STAssertEquals(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 sample describe(@"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 methods 1. Create a mock dependency 2. Inject it 3. Call the method 4. 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 can change implementations of private methods 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 apply despite 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 - merge nightmares
  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 your testing experience
  33. 33. Ending thoughts• Practice!
  34. 34. Thanks!
  35. 35. Questions

×