Slide 1

Slide 1 text

Web APIΛར༻͢Δ iOSΞϓϦͷςετٕ๏

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

cockscomb

Slide 4

Slide 4 text

id:cockscomb ΞϓϦέʔγϣϯΤϯδχΞ iOSΞϓϦɾWebΞϓϦέʔγϣϯ Perl, JavaScript, Objective-C ͸ͯͳϒϩάνʔϜ WWDC 2014

Slide 5

Slide 5 text

͸ͯͳϒϩά Presso B!KUMA Ψʔϧζ

Slide 6

Slide 6 text

͸ͯͳαϚʔΠϯλʔϯ Web APIΛར༻͢ΔiOSΞϓϦ࡞੒

Slide 7

Slide 7 text

–id:murakaming “iOS ଆͬ͟ͱݟ͚ͨͲɺ͜͏͍͏ حྷͳίʔυ͕খ͍͞αϯϓϧͰͳ͘ Ұࣜἧ͍ͬͯΔͷ͸ຊ౰ʹوॏͩ͠ ༗Γ೉͗͢Δɻ”

Slide 8

Slide 8 text

–id:griffin-stewie “ͦΕͳΓʹ࣮ઓܦݧ͕͋ΔਓͰ΋ ΍ͬͯͳͦ͞͏ͩͬͨΓ஌Βͳͦ͏ͳ͜ͱΛ αϥοͱݟͤͯ͘Ε͍ͯΔ”

Slide 9

Slide 9 text

Web APIΛར༻͢Δ iOSΞϓϦͷςετٕ๏

Slide 10

Slide 10 text

Web API JSON REST·ͨ͸Appઐ༻ APIόʔδϣϯ

Slide 11

Slide 11 text

API is living

Slide 12

Slide 12 text

ੜ͖͍ͯΔAPIͷͨΊͷ ςετ

Slide 13

Slide 13 text

ԿΛςετ͢Δͷ͔ ظ଴Ͳ͓ΓͷHTTP request͕ൃߦ͞ΕΔ URL (ϗετ΍ύεɺΫΤϦ) HTTP method, header, body ༷ʑͳHTTP responseʹର͢Δ;Δ·͍ Τϥʔ͕ى͖ͨͱ͖

Slide 14

Slide 14 text

ಓ۩ • OHHTTPStubs • NTLHTTPStubServer

Slide 15

Slide 15 text

OHHTTPStubs • HTTPͷ௨৴Λstub͢Δ • NSURLProtocolΛར༻͍ͯ͠Δ

Slide 16

Slide 16 text

__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]; });

Slide 17

Slide 17 text

[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; }];

Slide 18

Slide 18 text

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");

Slide 19

Slide 19 text

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]];

Slide 20

Slide 20 text

OHHTTPStubs • HTTP requestͷ༷ࢠΛݟΔ͜ͱ͕Ͱ͖Δ • ೚ҙͷHTTP responseΛฦ͢͜ͱ͕Ͱ͖Δ • ΤϥʔΛൃੜͤ͞ΒΕΔ • HTTP body͸औಘͰ͖ͳ͍

Slide 21

Slide 21 text

NLTHTTPStubServer • ΞϓϦͷ಺෦ͰαʔόʔΛಈ͔͢ • CocoaHTTPServerΛར༻ • http://localhost:12345/

Slide 22

Slide 22 text

#if defined(UNIT_TEST) static NSString *const kAPIRootURLString = @"http://localhost:12345/"; #else static NSString *const kAPIRootURLString = @"http://example.com/"; #endif

Slide 23

Slide 23 text

__block NLTHTTPStubServer *server; __block APIClient *client; ! beforeAll(^{ server = [[NLTHTTPStubServer alloc] init]; [server startServer]; client = [APIClient sharedClient]; }); ! afterAll(^{ [server stopServer]; }); ! afterEach(^{ [server clear]; });

Slide 24

Slide 24 text

[[[[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];

Slide 25

Slide 25 text

NLTHTTPStubServer • ࣮ࡍͷαʔόʔͱͯ͠ৼΔ෣͏ • ೚ҙͷHTTP responseΛฦ͢͜ͱ͕Ͱ͖Δ • HTTP bodyͷ༷ࢠΛݟΔ͜ͱ͕Ͱ͖Δ • Τϥʔ͸ൃੜͤ͞ΒΕͳ͍ • HTTP request͸Ұ෦औಘͰ͖ͳ͍

Slide 26

Slide 26 text

ಓ۩ • OHHTTPStubs • NTLHTTPStubServer

Slide 27

Slide 27 text

ςετͷϝϦοτ • ࣗ༝ͳHTTP response͕࡞ΕΔ • ࣮ࡍʹαʔόʔʹrequest͠ͳͯ͘Α͍ • αʔόʔαΠυͷ࣮૷Λ଴ͭඞཁ͕ͳ͍ • αʔόʔαΠυͷมߋΛࣄલʹࢼͤΔ • ͍͖ͳΓյΕΔͷΛ๷͛Δ

Slide 28

Slide 28 text

ςετ is ศར

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

PR

Slide 31

Slide 31 text

[PR] ৽αʔϏε΍Γ·͢ https://mackerel.io/ ϕʔλϢʔβʔ ࣄલड෇த!!

Slide 32

Slide 32 text

ੵۃ࠾༻த http://hatenacorp.jp/recruit/