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.5k
吉田を支える技術
cockscomb
0
2.3k
コーポレートサイトを静的化してAmplify Consoleにデプロイする
cockscomb
0
3.4k
ユーザインターフェイスと非同期処理
cockscomb
5
1.9k
GUIアプリケーションの構造と設計
cockscomb
10
10k
イカリング2におけるシングルページアプリケーション
cockscomb
2
7.5k
あなたの知らない UIKit の世界 — UITableView に UITextView を置きたい
cockscomb
1
7.5k
Other Decks in Programming
See All in Programming
ISUCON研修おかわり会 講義スライド
arfes0e2b3c
1
430
VS Code Update for GitHub Copilot
74th
2
630
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
51
33k
なぜ「共通化」を考え、失敗を繰り返すのか
rinchoku
1
640
CursorはMCPを使った方が良いぞ
taigakono
1
250
Node-RED を(HTTP で)つなげる MCP サーバーを作ってみた
highu
0
120
Porting a visionOS App to Android XR
akkeylab
0
420
NPOでのDevinの活用
codeforeveryone
0
800
生成AI時代のコンポーネントライブラリの作り方
touyou
1
170
Discover Metal 4
rei315
2
130
LINEヤフー データグループ紹介
lycorp_recruit_jp
1
2.4k
GitHub Copilot and GitHub Codespaces Hands-on
ymd65536
2
150
Featured
See All Featured
Product Roadmaps are Hard
iamctodd
PRO
54
11k
StorybookのUI Testing Handbookを読んだ
zakiyama
30
5.9k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
Speed Design
sergeychernyshev
32
1k
The Art of Programming - Codeland 2020
erikaheidi
54
13k
A better future with KSS
kneath
239
17k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
Designing Experiences People Love
moore
142
24k
Facilitating Awesome Meetings
lara
54
6.4k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
8
680
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/