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
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
A2UI という光を覗いてみる
satohjohn
1
130
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
280
Contextとはなにか
chiroruxx
1
320
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
200
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
470
AI時代のUIはどこへ行く?その2!
yusukebe
21
7.1k
JavaDoc 再入門
nagise
0
330
Lessons from Spec-Driven Development
simas
PRO
0
190
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
130
エンジニアと一緒にテストコードの設計と実装を改善した話
mototakatsu
0
170
技術記事、 専門家としてのプログラマ、 言語化
mizchi
13
5.8k
AIだと陥りがちなJakarta EE最新技術への移行時の落とし穴と解決策
tnagao7
0
110
Featured
See All Featured
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Ruling the World: When Life Gets Gamed
codingconduct
0
250
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
180
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
420
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
65
55k
The Curious Case for Waylosing
cassininazir
1
390
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
160
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
590
A Tale of Four Properties
chriscoyier
163
24k
Test your architecture with Archunit
thirion
1
2.3k
How to train your dragon (web standard)
notwaldorf
97
6.7k
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