Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
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
70
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
83
2013-05-15 The story of Taxi5.pl. How to get 2mln PLN from a VC
cocoaheadstricity
0
86
2013-04-16 iOS development speed up
cocoaheadstricity
0
100
2013-04-16 cocos2d & chipmunk
cocoaheadstricity
0
68
2013-03-07 iOS indie developer toolkit
cocoaheadstricity
1
82
2013-02-05 UICollectionView
cocoaheadstricity
0
190
2013-02-05 UXDesignForMobileApps
cocoaheadstricity
1
110
Other Decks in Programming
See All in Programming
エージェンティックRAGにAWSで入門しよう!
har1101
8
1.5k
A2UI という光を覗いてみる
satohjohn
1
130
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
730
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
220
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2k
ユニットテストの先へ:テスト技法で要求・仕様を整理するJava開発実践 / Beyond_Unit_Testing_Practical_Java_Development_Techniques_for_Organizing_Requirements_and_Specifications
shimashima35
0
390
タクシーアプリ『GO』の バックエンド開発のおける AI利活用と若者のすべて
pyama86
3
2k
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
540
CSC307 Lecture 17
javiergs
PRO
0
320
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
220
Claspは野良GASの夢をみるか
takter00
0
190
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
5.6k
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
330
40k
So, you think you're a good person
axbom
PRO
2
2.1k
Music & Morning Musume
bryan
47
7.2k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.4k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
170
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
250
Done Done
chrislema
186
16k
Code Review Best Practice
trishagee
74
20k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
160
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