iOS testing
Upcoming SlideShare
Loading in...5

iOS testing



Testing in iOS using Kiwi and OCMock frameworks

Testing in iOS using Kiwi and OCMock frameworks



Total Views
Views on SlideShare
Embed Views



0 Embeds 0

No embeds



Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

iOS testing iOS testing Presentation Transcript

  • Testing in iOS10.01.2013 by Tomasz Janeczko
  • About meTomasz Janeczko• iOS developer in Kainos• Enthusiast of business, electronics, Rails & Heroku• Organizer of first App Camp in UK and PL
  • 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", ^{ [[theValue(0) should] equal:theValue(0)]; }); });});
  • Kiwidescribe(@"Tested class", ^{ context(@"When created", ^{ it(@"should not fail", ^{ id viewController = [ViewController new]; [[viewController should]conformToProtocol:@protocol(UITableViewDelegate)]; }); });});
  • 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.
  • Compare to SenTesting Kit [[subject  should]  equal:anObject] compare  with STAssertEquals(subject,  anObject,  @”Should  be  equal”);
  • OCMock• Mocking and stubbing library for iOS• Quite versatile• Makes use of NSProxy magic
  • Sample workflows
  • 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];                });
  • 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 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];
  • 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
  • Accessing private methods
  • Accessing private methods @interface ViewController() - (void)startDownloadingTweets; @end ... [[mockController expect] startDownloadingTweets];
  • Static method testing• Through separation to a method@interface ViewController()- (NSUserDefaults *)userDefaults; mockDefaults = [OCMockObject mockForClass:[NSUserDefaults class]];[[[mockDefaults expect] andReturn:@"Setting"] valueForKey:[OCMArg any]];[[[mockController stub] andReturn:mockDefaults] userDefaults];
  • 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);}
  • 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 - merge nightmares
  • 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
  • Ending thoughts• Practice!
  • Thanks!
  • Questions