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.9k
GraphQL放談
cockscomb
4
2k
GraphQL Highway
cockscomb
28
8.6k
吉田を支える技術
cockscomb
0
2.4k
コーポレートサイトを静的化してAmplify Consoleにデプロイする
cockscomb
0
3.4k
ユーザインターフェイスと非同期処理
cockscomb
5
1.9k
GUIアプリケーションの構造と設計
cockscomb
10
10k
イカリング2におけるシングルページアプリケーション
cockscomb
2
7.6k
あなたの知らない UIKit の世界 — UITableView に UITextView を置きたい
cockscomb
1
7.5k
Other Decks in Programming
See All in Programming
2025年版 サーバーレス Web アプリケーションの作り方
hayatow
23
25k
Catch Up: Go Style Guide Update
andpad
0
170
GraphQL×Railsアプリのデータベース負荷分散 - 月間3,000万人利用サービスを無停止で
koxya
1
1.1k
Swift Concurrency - 状態監視の罠
objectiveaudio
2
450
ててべんす独演会〜Flowの全てを語ります〜
tbsten
1
220
SpecKitでどこまでできる? コストはどれくらい?
leveragestech
0
510
Advance Your Career with Open Source
ivargrimstad
0
330
高度なUI/UXこそHotwireで作ろう Kaigi on Rails 2025
naofumi
4
3.4k
Pythonスレッドとは結局何なのか? CPython実装から見るNoGIL時代の変化
curekoshimizu
4
1.3k
フロントエンド開発に役立つクライアントプログラム共通のノウハウ / Universal client-side programming best practices for frontend development
nrslib
7
3.9k
そのpreloadは必要?見過ごされたpreloadが技術的負債として爆発した日
mugitti9
2
3k
CSC305 Lecture 03
javiergs
PRO
0
230
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
6.1k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Site-Speed That Sticks
csswizardry
11
880
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
19
1.2k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
A Tale of Four Properties
chriscoyier
160
23k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.6k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.1k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
2.6k
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/