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
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
パスワード再設定メールのURLについて知っておこう
uyuki234
0
200
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
6
2k
私なりのハーネスエンジニアリング ~独自の言語処理系の開発を通して~
seosoft
0
150
AI時代のFlutter品質設計 — アプリ品質を守るQuality Layers
omatty198
0
320
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
300
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
240
Seven New Principles of Software Engineering
yegor256
0
390
Web Framework Benchmark Battle 2026, Any%
a_matsuda
3
3.1k
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
240
golang-bob.pdf
iwatsukayura
0
150
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
3
1.8k
AI-Powered Domain-Driven Design
ziobrando
0
360
Featured
See All Featured
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
870
What the history of the web can teach us about the future of AI
inesmontani
PRO
2
770
Fireside Chat
paigeccino
43
4.1k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
360
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3.1k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
320
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
300
The untapped power of vector embeddings
frankvandijk
2
2k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
1k
Build your cross-platform service in a week with App Engine
jlugia
234
19k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
500
Building Better People: How to give real-time feedback that sticks.
wjessup
371
20k
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