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
Test techniques for iOS app using Web API
Search
cockscomb
April 24, 2014
Programming
4
38k
Test techniques for iOS app using Web API
My presentation at Consumer Service Engineer MeetUp Vol.1 ~iOS編~ (
http://eventdots.jp/event/47442
)
cockscomb
April 24, 2014
Tweet
Share
More Decks by cockscomb
See All by cockscomb
jq at the Shortcuts
cockscomb
1
1.8k
GraphQL放談
cockscomb
4
1.9k
GraphQL Highway
cockscomb
28
8.3k
吉田を支える技術
cockscomb
0
2.2k
コーポレートサイトを静的化してAmplify Consoleにデプロイする
cockscomb
0
3.4k
ユーザインターフェイスと非同期処理
cockscomb
5
1.8k
GUIアプリケーションの構造と設計
cockscomb
10
10k
イカリング2におけるシングルページアプリケーション
cockscomb
2
7.4k
あなたの知らない UIKit の世界 — UITableView に UITextView を置きたい
cockscomb
1
7.4k
Other Decks in Programming
See All in Programming
コミュニティ駆動 AWS CDK ライブラリ「Open Constructs Library」 / community-cdk-library
gotok365
2
250
Boost Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
1k
クックパッド検索システム統合/Cookpad Search System Consolidation
giga811
0
120
Boos Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
540
CDK開発におけるコーディング規約の運用
yamanashi_ren01
2
260
なぜイベント駆動が必要なのか - CQRS/ESで解く複雑系システムの課題 -
j5ik2o
14
4.8k
AIプログラミング雑キャッチアップ
yuheinakasaka
19
5k
良いコードレビューとは
danimal141
9
5.1k
Datadog DBMでなにができる? JDDUG Meetup#7
nealle
0
160
kintone開発を効率化するためにチームで試した施策とその結果を大放出!
oguemon
0
310
SwiftUI移行のためのインプレッショントラッキング基盤の構築
kokihirokawa
0
170
CSS Linter による Baseline サポートの仕組み
ryo_manba
1
160
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.2k
GraphQLの誤解/rethinking-graphql
sonatard
69
10k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.3k
Become a Pro
speakerdeck
PRO
26
5.2k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3k
How GitHub (no longer) Works
holman
314
140k
VelocityConf: Rendering Performance Case Studies
addyosmani
328
24k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
260
Designing for humans not robots
tammielis
250
25k
Transcript
Web APIΛར༻͢Δ iOSΞϓϦͷςετٕ๏
None
cockscomb
id:cockscomb ΞϓϦέʔγϣϯΤϯδχΞ iOSΞϓϦɾWebΞϓϦέʔγϣϯ Perl, JavaScript, Objective-C ͯͳϒϩάνʔϜ WWDC 2014
ͯͳϒϩά Presso B!KUMA Ψʔϧζ
ͯͳαϚʔΠϯλʔϯ Web APIΛར༻͢ΔiOSΞϓϦ࡞
–id:murakaming “iOS ଆͬ͟ͱݟ͚ͨͲɺ͜͏͍͏ حྷͳίʔυ͕খ͍͞αϯϓϧͰͳ͘ Ұࣜἧ͍ͬͯΔͷຊʹوॏͩ͠ ༗Γ͗͢Δɻ”
–id:griffin-stewie “ͦΕͳΓʹ࣮ઓܦݧ͕͋ΔਓͰ ͬͯͳͦ͞͏ͩͬͨΓΒͳͦ͏ͳ͜ͱΛ αϥοͱݟͤͯ͘Ε͍ͯΔ”
Web APIΛར༻͢Δ iOSΞϓϦͷςετٕ๏
Web API JSON REST·ͨAppઐ༻ APIόʔδϣϯ
API is living
ੜ͖͍ͯΔAPIͷͨΊͷ ςετ
ԿΛςετ͢Δͷ͔ ظͲ͓ΓͷHTTP request͕ൃߦ͞ΕΔ URL (ϗετύεɺΫΤϦ) HTTP method, header, body ༷ʑͳHTTP
responseʹର͢Δ;Δ·͍ Τϥʔ͕ى͖ͨͱ͖
ಓ۩ • OHHTTPStubs • NTLHTTPStubServer
OHHTTPStubs • HTTPͷ௨৴Λstub͢Δ • NSURLProtocolΛར༻͍ͯ͠Δ
__block APIClient *client; __block NSURLRequest *lastRequest; __block OHHTTPStubsResponse *preferredResponse; !
beforeAll(^{ client = [APIClient sharedClient]; ! [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { if ( [request.HTTPMethod isEqual:@"GET"] && [request.URL.host isEqual:@"example.com"] && [request.URL.path isEqual:@"/api/entries.json"] ) { lastRequest = request; return YES; } return NO; } withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) { return preferredResponse; }]; }); ! afterEach(^{ lastRequest = nil; preferredResponse = nil; }); ! afterAll(^{ [OHHTTPStubs removeAllStubs]; });
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { if ( [request.HTTPMethod isEqual:@"GET"] && [request.URL.host
isEqual:@"example.com"] && [request.URL.path isEqual:@"/api/entries.json"] ) { lastRequest = request; return YES; } return NO; } withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) { return preferredResponse; }];
NSString *userAgent = lastRequest.allHTTPHeaderFields[@"User-Agent"]; expect([userAgent hasPrefix:@"BKUMAGirls"]).to.beTruthy(); ! ! NSURL *URL
= lastRequest.URL; NSDictionary *query = [CMDQueryStringSerialization dictionaryWithQueryString:URL.query]; ! expect(query[@"entry_id"]).to.equal(@"1234567890");
preferredResponse = [OHHTTPStubsResponse responseWithFileAtPath: OHPathForFileInBundle(@"entries.json", nil) statusCode:200 headers:@{ @"Content-Type" :
@"application/json", }]; ! ! preferredResponse = [OHHTTPStubsResponse responseWithJSONObject:@{ @"test" : @"ok", } statusCode:200 headers:@{ @"Content-Type" : @"application/json", }]; ! ! preferredResponse = [OHHTTPStubsResponse responseWithError: [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorNetworkConnectionLost userInfo:nil]];
OHHTTPStubs • HTTP requestͷ༷ࢠΛݟΔ͜ͱ͕Ͱ͖Δ • ҙͷHTTP responseΛฦ͢͜ͱ͕Ͱ͖Δ • ΤϥʔΛൃੜͤ͞ΒΕΔ •
HTTP bodyऔಘͰ͖ͳ͍
NLTHTTPStubServer • ΞϓϦͷ෦ͰαʔόʔΛಈ͔͢ • CocoaHTTPServerΛར༻ • http://localhost:12345/
#if defined(UNIT_TEST) static NSString *const kAPIRootURLString = @"http://localhost:12345/"; #else static
NSString *const kAPIRootURLString = @"http://example.com/"; #endif
__block NLTHTTPStubServer *server; __block APIClient *client; ! beforeAll(^{ server =
[[NLTHTTPStubServer alloc] init]; [server startServer]; client = [APIClient sharedClient]; }); ! afterAll(^{ [server stopServer]; }); ! afterEach(^{ [server clear]; });
[[[[server expect] forPath:@"/api/bookmarks.json" HTTPMethod:@"POST"] andCheckPostBody:^(NSData *postBody) { ! NSString *body
= [[NSString alloc] initWithData:postBody encoding:NSUTF8StringEncoding]; ! NSDictionary *parameters = [CMDQueryStringSerialization dictionaryWithQueryString:body]; ! expect(parameters[@"entry_id"]).to.equal(@"1234567890"); ! }] andPlainResponse:[@"1" dataUsingEncoding:NSUTF8StringEncoding]]; ! ... ! [server verify];
NLTHTTPStubServer • ࣮ࡍͷαʔόʔͱͯ͠ৼΔ͏ • ҙͷHTTP responseΛฦ͢͜ͱ͕Ͱ͖Δ • HTTP bodyͷ༷ࢠΛݟΔ͜ͱ͕Ͱ͖Δ •
Τϥʔൃੜͤ͞ΒΕͳ͍ • HTTP requestҰ෦औಘͰ͖ͳ͍
ಓ۩ • OHHTTPStubs • NTLHTTPStubServer
ςετͷϝϦοτ • ࣗ༝ͳHTTP response͕࡞ΕΔ • ࣮ࡍʹαʔόʔʹrequest͠ͳͯ͘Α͍ • αʔόʔαΠυͷ࣮Λͭඞཁ͕ͳ͍ • αʔόʔαΠυͷมߋΛࣄલʹࢼͤΔ
• ͍͖ͳΓյΕΔͷΛ͛Δ
ςετ is ศར
None
PR
[PR] ৽αʔϏεΓ·͢ https://mackerel.io/ ϕʔλϢʔβʔ ࣄલडத!!
ੵۃ࠾༻த http://hatenacorp.jp/recruit/