iOS testing
Upcoming SlideShare
Loading in...5
×
 

iOS testing

on

  • 1,340 views

Testing in iOS using Kiwi and OCMock frameworks

Testing in iOS using Kiwi and OCMock frameworks

Statistics

Views

Total Views
1,340
Views on SlideShare
1,340
Embed Views
0

Actions

Likes
2
Downloads
9
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

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.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
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;@end...id 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