Slide 1

Slide 1 text

௨৴ॲཧΛࠩ͠ସ͑ͯΈͨ࿩

Slide 2

Slide 2 text

ࣗݾ঺հ • ాதୡ໵ (@tattn) • Ϡϑʔͷ2016೥৽ଔ

Slide 3

Slide 3 text

Qiitaͱ͔Twitterͱ͔΍ͬͯ·͢ • ։ൃ͕ര଎ʹͳΔSwift༻XcodeϓϥάΠϯΛ·ͱΊͯΈͨ • ࢖͏ͱख์ͤͳ͘ͳΔSwift Extensionू (Swift3൛) @tanakasan2525

Slide 4

Slide 4 text

APIͷϢχοτςετͲ͏ͯ͠·͢ ͔ʁ

Slide 5

Slide 5 text

DIʁ ϥΠϒϥϦʁ

Slide 6

Slide 6 text

MockingjayศརͰ͢ΑͶ

Slide 7

Slide 7 text

Mockingjay https://github.com/kylef/Mockingjay let body = [ "user": "Kyle" ] stub(uri("/{user}/{repository}"), json(body))

Slide 8

Slide 8 text

Ͳ͏͍͏࢓૊ΈͰಈ͍ͯΔΜͩΖ͏ !

Slide 9

Slide 9 text

ௐ΂ͯΈΔͱ

Slide 10

Slide 10 text

URLProtocolͱMethod Swizzling Λ࢖ͬͯ௨৴ॲཧΛࠩ͠ସ͍͑ͯ·͠ ͨ

Slide 11

Slide 11 text

URLProtocol https://developer.apple.com/reference/foundation/urlprotocol αϙʔτ֎ͷϓϩτίϧͰ௨৴͢Δ৔߹΍ ϦΫΤετΛಠࣗͷํ๏Ͱॲཧ͢Δ࣌ʹ࢖͏Ϋϥεɻ

Slide 12

Slide 12 text

Mock༻ͷURLProtocol public class MockURLProtocol: URLProtocol { override open func startLoading() { let jsonString = "{\"mock\": \"data\"}" let json = jsonString.data(using: .utf8)! self.client?.urlProtocol(self, didLoad: json) self.client?.urlProtocolDidFinishLoading(self) } // ͦͷଞϝιου͸লུ }

Slide 13

Slide 13 text

Method SwizzlingͰϞοΫ༻ͷURLProtocol ʹࠩ͠ସ͑ public extension URLSessionConfiguration { public class func setup() { let `default` = class_getClassMethod(URLSessionConfiguration.self, #selector(getter: URLSessionConfiguration.default)) let swizzled = class_getClassMethod(URLSessionConfiguration.self, #selector(getter: URLSessionConfiguration.mock)) method_exchangeImplementations(`default`, swizzled) } private dynamic class var mock: URLSessionConfiguration { let configuration = self.mock configuration.protocolClasses?.insert(MockURLProtocol.self, at: 0) URLProtocol.registerClass(MockURLProtocol.self) return configuration } }

Slide 14

Slide 14 text

ֶ͔ͤͬ͘ΜͩͷͰϥΠϒϥϦԽ͠· ͨ͠ !

Slide 15

Slide 15 text

Replacer https://github.com/tattn/Replacer ௨৴ͷελϒԽ΍Method SwizzlingΛαϙʔτ͢ΔϥΠϒϥϦ

Slide 16

Slide 16 text

Method ChainͰΦϓγϣϯΛઃఆ͠·͢ self.urlStub .url("echo.jsontest.com/[a-z]+/.*") .httpMethod(.post) .json(["test": "data"]) .delay(1.5)

Slide 17

Slide 17 text

QuickͱAlamofireͰͷελϒԽ describe("Quick compatibility test") { it("returns mock data") { let url = "http://echo.jsontest.com/key/value/one/two" var json: [String: String]? Alamofire.request(url, method: .post).responseJSON { response in json = response.result.value as? [String: String] } expect(json?["test"]).toEventually(equal("data")) } }

Slide 18

Slide 18 text

ओͳػೳ • ௨৴ͷελϒԽ • XCTestҎ֎ (Host Application΋ؚΉ) Ͱ΋࢖༻Մೳ • Method Swizzlingͷαϙʔτػೳ ͳͲͰ͢ɻ

Slide 19

Slide 19 text

ྑ͔ͬͨΒ࢖ͬͯΈ͍ͯͩ͘͞ ! (ʁʁ)ʻ ܅͸⭐͕େ޷͖ͳϑϨϯζͳΜͩͶʂ

Slide 20

Slide 20 text

͋ɺͦ͏͍͑͹ɺɺɺ

Slide 21

Slide 21 text

࡞͍ͬͯΔ࣌ʹSwiftͷόάʹؾ͕෇͖·ͨ͠ ؀ڥ: Xcode 8.2, Swift 3.0.2

Slide 22

Slide 22 text

άϩʔόϧఆٛ͞Εͨؔ਺ʹϞδϡʔϧ໊Λ෇͚ Δͱɺ@discardableResult͕ਖ਼ৗʹಈ࡞͠ͳ͍

Slide 23

Slide 23 text

ઌఔௐ΂ͯΈΔͱɺमਖ਼͞ΕͨΈ͍ͨͰ͢ ! https://bugs.swift.org/browse/SR-3665 Fix @discardableResult when invoking function with explicit namespace #7201

Slide 24

Slide 24 text

SwiftͷਐԽɾվળ͸ࢭ ·Βͳ͍Ͱ͢Ͷʂ !

Slide 25

Slide 25 text

͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝ ·ͨ͠ʂ