Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
2013-01-10 iOS testing
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
CocoaHeads Tricity
January 10, 2013
Programming
81
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
2013-01-10 iOS testing
CocoaHeads Tricity
January 10, 2013
More Decks by CocoaHeads Tricity
See All by CocoaHeads Tricity
2013-05-15 Threads. Why and how.
cocoaheadstricity
0
88
2013-05-15 The story of Taxi5.pl. How to get 2mln PLN from a VC
cocoaheadstricity
0
89
2013-04-16 iOS development speed up
cocoaheadstricity
0
120
2013-04-16 cocos2d & chipmunk
cocoaheadstricity
0
80
2013-03-07 iOS indie developer toolkit
cocoaheadstricity
1
93
2013-02-05 UICollectionView
cocoaheadstricity
0
200
2013-02-05 UXDesignForMobileApps
cocoaheadstricity
1
130
Other Decks in Programming
See All in Programming
Jetpack Compose Mechanisms
skydoves
3
900
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
130
Python Lambdaにおけるテストしやすい設計とAI支援の活用 / Designing Testable Python Lambda Functions with AI
kitano_yuichi
1
250
AmebaブログはKMPから卒業します
kmars0605
0
310
LLM 101
dalinaum
0
360
Spec-driven Development with AI
simas
PRO
0
2.2k
TanStack Vue Query と Pinia Colada から学ぶ非同期状態の型設計
aoshi
0
450
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
300
baseline으로 마이그레이션, 리팩토링 안전하게 맡기기
fornewid
1
560
GraphQL の onError と Nullability のこれから
quramy
0
200
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
12
11k
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
340
Featured
See All Featured
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
230
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
470
Navigating Weather and Climate Data
rabernat
0
570
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
460
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
410
The Curious Case for Waylosing
cassininazir
1
590
Exploring anti-patterns in Rails
aemeredith
4
550
Intergalactic Javascript Robots from Outer Space
tanoku
273
28k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
Transcript
Testing in iOS 10.01.2013 by Tomasz Janeczko
About me Tomasz 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?
None
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 fault Writing tests after writing code
Separation of concerns
Separation of concerns • Let’s separate out the UI code
• Same for services interaction
Demo of tests
Writing tests Meet 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)]; }); }); });
Kiwi describe(@"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 id's • [[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 functionality viewController = [ViewController new]; mockController = [OCMockObject partialMockForObject:viewController]; // Create the mock and change implementation to return our class id 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 swizzling void 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