Upgrade to Pro — share decks privately, control downloads, hide ads and more …

単体テストのハジメ

 単体テストのハジメ

iOS Test Night #15 で発表した資料です

yokoya-s000

July 26, 2017
Tweet

More Decks by yokoya-s000

Other Decks in Technology

Transcript

  1. ୯ମςετͷϋδϝ
    !ZPLPZBT UXJUUFS*%ZPLPZBT

    View full-size slide

  2. ࣗݾ঺հ
    ˙ OBNFZPLPZBT
    ˙ UXJUUFS*%ZPLPZBT
    ˙ KPCגࣜձࣾNJYJͰJ04ΤϯδχΞ΍͍ͬͯ·͢

    View full-size slide

  3. ୯ମςετͷൃද͕গͳ͍ͱ
    ฉ͍ͨͷͰɺ
    ୯ମςετͷ࿩Λ͠·͢

    View full-size slide

  4. ʮςετ͍ͨ͜͠ͱʯ
    ͸ԿͰ͠ΐ͏͔

    View full-size slide

  5. doSomething(x)
    Ҿ਺ ໭Γ஋
    ςετ͍ͨ͜͠ͱ
    ˙ ᶃ໌ࣔతͳೖग़ྗ

    View full-size slide

  6. doSomething(x)
    Ҿ਺ ໭Γ஋
    ςετ͕ॻ͖΍͍͢
    ςετ͍ͨ͜͠ͱ
    ˙ ᶃ໌ࣔతͳೖग़ྗ

    View full-size slide

  7. ςετ͍ͨ͜͠ͱ
    ˙ ᶄ҉໧తͳೖग़ྗ
    େҬม਺ͳͲ
    ଞͷςετ͕յ͔͢΋ ଞͷςετΛյ͔͢΋
    େҬม਺ͳͲ
    doSomething(x)
    Ҿ਺ ໭Γ஋

    View full-size slide

  8. ςετ͍ͨ͜͠ͱ
    ˙ ᶄ҉໧తͳೖग़ྗ
    େҬม਺ͳͲ
    ଞͷςετ͕յ͔͢΋ ଞͷςετΛյ͔͢΋
    େҬม਺ͳͲ
    doSomething(x)
    Ҿ਺ ໭Γ஋
    ςετ͕ॻ͖΍͍͢ʜ

    View full-size slide

  9. ςετ͍ͨ͜͠ͱ
    ˙ ҉໧తͳೖग़ྗ
    େҬม਺ͳͲ
    େҬม਺ͳͲ
    doSomething(x)
    Ҿ਺ ໭Γ஋
    ଞͷςετ͕յ͔͢΋ ଞͷςετΛյ͔͢΋

    View full-size slide

  10. ςετ͍ͨ͜͠ͱ
    ˙ ҉໧తͳೖग़ྗ
    େҬม਺ͳͲ
    େҬม਺ͳͲ
    doSomething(x)
    Ҿ਺ ໭Γ஋
    ଞͷςετ͕յ͔͢΋ ଞͷςετΛյ͔͢΋
    ͭΒ͍

    View full-size slide

  11. ςετ͍ͨ͜͠ͱ
    ˙ ҉໧తͳೖग़ྗ
    େҬม਺ͳͲ
    େҬม਺ͳͲ
    doSomething(x)
    Ҿ਺ ໭Γ஋
    ଞͷςετ͕յ͔͢΋ ଞͷςετΛյ͔͢΋
    ྫ͑͹Ͳ͏͍͏ςετʁ

    View full-size slide

  12. ҉໧తͳೖग़ྗͷςετྫ
    ˙ 6TFS%FGBVMUT͔Βऔಘͨ͠஋Λ࢖͏ؔ਺Λςετ͢Δ৔߹
    class HogeTests: XCTestCase {
    func testHoge() {
    UserDefaults.resetStandardUserDefaults()
    let testValue = 10
    UserDefaults.standard.set(testValue, forKey: "hoge")
    // something to do...
    UserDefaults.standard.removeObject(forKey: "hoge")
    }
    }

    View full-size slide

  13. class HogeTests: XCTestCase {
    func testHoge() {
    UserDefaults.resetStandardUserDefaults()
    let testValue = 10
    UserDefaults.standard.set(testValue, forKey: "hoge")
    // something to do...
    UserDefaults.standard.removeObject(forKey: "hoge")
    }
    }
    ҉໧తͳೖग़ྗͷςετྫ
    ˙ 6TFS%FGBVMUT͔Βऔಘͨ͠஋Λ࢖͏ؔ਺Λςετ͢Δ৔߹
    ຊମίʔυɺ΋͘͠͸ଞͷςετ͔Β
    มߋ͞Ε͍ͯΔՄೳੑ͕͋ΔͷͰɺ
    6TFS%FGBVMUTΛॳظঢ়ଶʹ͔ͯ͠Βελʔτ

    View full-size slide

  14. class HogeTests: XCTestCase {
    func testHoge() {
    UserDefaults.resetStandardUserDefaults()
    let testValue = 10
    UserDefaults.standard.set(testValue, forKey: "hoge")
    // something to do...
    UserDefaults.standard.removeObject(forKey: "hoge")
    }
    }
    ҉໧తͳೖग़ྗͷςετྫ
    ˙ 6TFS%FGBVMUT͔Βऔಘͨ͠஋Λ࢖͏ؔ਺Λςετ͢Δ৔߹
    ςετΛߦ͏ͨΊʹʮࣄલʹೖ͍ͬͯͯཉ͍͠஋ʯΛ
    6TFS%FGBVMUTʹ௚઀ॻ͖ࠐΉ

    View full-size slide

  15. class HogeTests: XCTestCase {
    func testHoge() {
    UserDefaults.resetStandardUserDefaults()
    let testValue = 10
    UserDefaults.standard.set(testValue, forKey: "hoge")
    // something to do...
    UserDefaults.standard.removeObject(forKey: "hoge")
    }
    }
    ҉໧తͳೖग़ྗͷςετྫ
    ˙ 6TFS%FGBVMUT͔Βऔಘͨ͠஋Λ࢖͏ؔ਺Λςετ͢Δ৔߹
    ຊମίʔυɺ΋͘͠͸ଞͷςετ΁

    ӨڹΛ༩͑ͳ͍ͨΊʹɺ
    6TFS%FGBVMUTʹՃ͑ͨมߋΛऔΓফ͢

    View full-size slide

  16. ҉໧తͳೖग़ྗͷςετྫ
    ˙ 6TFS%FGBVMUTΛ௚઀৮Δͱ͕͜͜ਏ͍
    ɾ༩͑ͨมߋΛফ͠๨ΕΔͱɺຊମ࣮ߦ࣌΍ଞͷςετʹӨڹ͢Δ
    ɾςετߦ͏ͱ΋Εͳ͘
    ʮ6TFS%FGBVMUT΁ͷૢ࡞෭࡞༻ʯ͕ੜͯ͡͠·͏
    ෭࡞༻ͳ͘ςετ͍ͨ͠ʂ

    View full-size slide

  17. ෭࡞༻ͳ͘ςετΛߦ͏ͨΊʹ
    ˙ ҉໧తͳೖग़ྗ
    େҬม਺ͳͲ
    େҬม਺ͳͲ
    doSomething(x)
    Ҿ਺ ໭Γ஋
    ελϒͱ͍͏ख๏
    Λ࢖͍·͢
    εύΠͱ͍͏ख๏
    Λ࢖͍·͢

    View full-size slide

  18. ҉໧తೖྗͷςετΛ
    ͢ΔͨΊʹελϒΛ࢖͏
    ຊ୊ͦͷ̍

    View full-size slide

  19. doSomething(x)
    Ҿ਺
    େҬม਺ͳͲ
    ࣄલʹઃఆͨ͠ৼΔ෣͍Λ͢Δ

    ِ෺ͷΦϒδΣΫτ
    ελϒ
    ໭Γ஋
    ˞ࢲ͕͜Ε͔Βઆ໌͢ΔʮελϒʯͷৼΔ෣͍͸্هͷ΋ͷ
    ʹͳΓ·͢ ಉ໊ͰผͷఆٛΛࢦ͢͜ͱ΋͋ΔͨΊ

    ҉໧తೖྗͷςετΛ͢ΔͨΊʹελϒΛ࢖͏

    View full-size slide

  20. ҉໧తೖྗͷςετΛ͢ΔͨΊʹελϒΛ࢖͏
    ˙ ཁ݅6TFS%FGBVMUT͔Βऔಘͨ͠஋ *OU
    Ҿ਺໭Γ஋
    class Input {
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }

    View full-size slide

  21. ҉໧తೖྗͷςετΛ͢ΔͨΊʹελϒΛ࢖͏
    ˙ ཁ݅6TFS%FGBVMUT͔Βऔಘͨ͠஋ *OU
    Ҿ਺໭Γ஋
    class Input {
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }
    େҬม਺͔Βऔಘ͍ͯ͠Δ

    View full-size slide

  22. ҉໧తೖྗͷςετΛ͢ΔͨΊʹελϒΛ࢖͏
    ˙ ཁ݅6TFS%FGBVMUT͔Βऔಘͨ͠஋ *OU
    Ҿ਺໭Γ஋
    class Input {
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }
    େҬม਺͔Βऔಘ͍ͯ͠Δ
    ςετ࣌͸ِ෺ʹࠩ͠ସ͍͑ͨ

    View full-size slide

  23. ҉໧తೖྗͷςετΛ͢ΔͨΊʹελϒΛ࢖͏
    ˙ ཁ݅6TFS%FGBVMUT͔Βऔಘͨ͠஋ *OU
    Ҿ਺໭Γ஋
    class Input {
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }
    େҬม਺͔Βऔಘ͍ͯ͠Δ
    ςετ࣌͸ِ෺ʹࠩ͠ସ͍͑ͨ
    ελϒΛ࢖͍͍ͨ

    View full-size slide

  24. ҉໧తೖྗͷςετΛ͢ΔͨΊʹελϒΛ࢖͏
    ˙ ཁ݅6TFS%FGBVMUT͔Βऔಘͨ͠஋ *OU
    Ҿ਺໭Γ஋
    class Input {
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }
    ςετ࣌͸ِ෺ʹࠩ͠ସ͍͑ͨ
    ελϒΛ࢖͍͍ͨ
    ελϒΛ࢖͑Δঢ়ଶʹ͢Δʂ
    େҬม਺͔Βऔಘ͍ͯ͠Δ

    View full-size slide

  25. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    multiplication(int:)
    Ҿ਺
    6TFS%FGBVMUT ελϒ
    ໭Γ஋
    6TFS%FGBVMU͔Β௚઀औಘ͸ͤͣʹɺ

    ৼΔ෣͍Λ੍ޚͰ͖ΔΦϒδΣΫτΛڬΉ

    View full-size slide

  26. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶃ੍ޚ͍ͨ͠ৼΔ෣͍Λ1SPUPDPMʹ͢Δ
    protocol ReadableRepositoryContract {
    func read() -> Int
    }

    View full-size slide

  27. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶄ1SPUPDPMʹ४ڌͨ͠ΫϥεΛ࡞੒͢Δ
    class ReadableRepository: ReadableRepositoryContract {
    func read() -> Int {
    return UserDefaults.standard.integer(forKey: "base")
    }
    }

    View full-size slide

  28. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తೖྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ
    class Input {
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }
    }

    View full-size slide

  29. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    class Input {
    private let repository: ReadableRepositoryContract
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }
    }
    ᶅ҉໧తೖྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ

    View full-size slide

  30. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    class Input {
    private let repository: ReadableRepositoryContract
    init (repository: ReadableRepositoryContract) {
    self.repository = repository
    }
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }
    }
    ᶅ҉໧తೖྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ

    View full-size slide

  31. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    class Input {
    private let repository: ReadableRepositoryContract
    init (repository: ReadableRepositoryContract) {
    self.repository = repository
    }
    func multiplication(int: Int) -> Int {
    let base = UserDefaults.standard.integer(forKey: “base")
    return base * int
    }
    }
    ᶅ҉໧తೖྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ

    View full-size slide

  32. class Input {
    private let repository: ReadableRepositoryContract
    init (repository: ReadableRepositoryContract) {
    self.repository = repository
    }
    func multiplication(int: Int) -> Int {
    let base = self.repository.read()
    return base * int
    }
    }
    ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తೖྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ

    View full-size slide

  33. class Input {
    private let repository: ReadableRepositoryContract
    init (repository: ReadableRepositoryContract) {
    self.repository = repository
    }
    func multiplication(int: Int) -> Int {
    let base = self.repository.read()
    return base * int
    }
    }
    ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తೖྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ
    ˙ ཁ݅6TFS%FGBVMUT͔Βऔಘͨ͠஋ *OU
    Ҿ਺໭Γ஋

    View full-size slide

  34. class Input {
    private let repository: ReadableRepositoryContract
    init (repository: ReadableRepositoryContract) {
    self.repository = repository
    }
    func multiplication(int: Int) -> Int {
    let base = self.repository.read()
    return base * int
    }
    }
    ελϒΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తೖྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ
    ˙ ཁ݅6TFS%FGBVMUT͔Βऔಘͨ͠஋ *OU
    Ҿ਺໭Γ஋
    ˙ ཁ݅3FQPTJUPSZ͔Βऔಘͨ͠஋ *OU
    Ҿ਺໭Γ஋

    View full-size slide

  35. ελϒΛ࢖͏४උ͸Ͱ͖ͨ

    View full-size slide

  36. ελϒΛ࢖ͬͯςετΛॻ͘
    ελϒΛ࢖͏४උ͸Ͱ͖ͨ

    View full-size slide

  37. ελϒΛ࢖ͬͯςετΛॻ͘
    class ReadableRepositoryStub: ReadableRepositoryContract {
    private let base: Int
    init(base: Int) {
    self.base = base
    }
    func read() -> Int {
    return self.base
    }
    }
    1SPUPDPMʹ४ڌͨ͠ελϒΛ࡞੒͢Δ

    View full-size slide

  38. class ReadableRepositoryStub: ReadableRepositoryContract {
    private let base: Int
    init(base: Int) {
    self.base = base
    }
    func read() -> Int {
    return self.base
    }
    }
    ελϒΛ࢖ͬͯςετΛॻ͘
    1SPUPDPMʹ४ڌͨ͠ελϒΛ࡞੒͢Δ
    ʮِ෺ͷৼΔ෣͍ʯΛߦͳ͍ͬͯΔՕॴ

    View full-size slide

  39. class InputTests: XCTestCase {
    func testMultiplication() {
    let base = 5
    let int = 2
    let expected = 10
    }
    }
    ˙ ςετέʔε
    ɾظ଴͕ฦͬͯ͘Δ
    ελϒΛ࢖ͬͯςετΛॻ͘
    ɾঢ়گCBTF JOUͷ࣌

    View full-size slide

  40. class InputTests: XCTestCase {
    func testMultiplication() {
    let base = 5
    let int = 2
    let expected = 10
    let repositoryStub = ReadableRepositoryStub(base: base)
    let input = Input(repository: repositoryStub)
    }
    }
    ɾঢ়گCBTF JOUͷ࣌
    ˙ ςετέʔε
    ɾظ଴͕ฦͬͯ͘Δ
    ελϒΛ࢖ͬͯςετΛॻ͘
    ελϒΛࠩ͠ࠐΉ

    View full-size slide

  41. class InputTests: XCTestCase {
    func testMultiplication() {
    let base = 5
    let int = 2
    let expected = 10
    let repositoryStub = ReadableRepositoryStub(base: base)
    let input = Input(repository: repositoryStub)
    let actual = input.multiplication(int: int)
    XCTAssertEqual(actual, expected)
    }
    }
    ɾঢ়گJOU CBTFͷ࣌
    ˙ ςετέʔε
    ɾظ଴͕ฦͬͯ͘Δ
    ελϒΛ࢖ͬͯςετΛॻ͘
    தͰελϒ͕࢖ΘΕ͍ͯΔ

    View full-size slide

  42. ҉໧తग़ྗͷςετΛ
    ͢ΔͨΊʹεύΠΛ࢖͏
    ຊ୊ͦͷ̎

    View full-size slide

  43. doSomething(x)
    Ҿ਺ ໭Γ஋
    େҬม਺ͳͲ
    ِ෺ͷؔ਺΍ΦϒδΣΫτͰɺ

    ݺͼग़͠΍ࣗ਎΁ͷมߋΛه࿥͢Δ
    εύΠ
    ҉໧తग़ྗͷςετΛ͢ΔͨΊʹεύΠΛ࢖͏

    View full-size slide

  44. ҉໧తग़ྗͷςετΛ͢ΔͨΊʹεύΠΛ࢖͏
    ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ6TFS%FGBVMUTʹอଘ͢Δ
    class Output {
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }

    View full-size slide

  45. class Output {
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }
    ҉໧తग़ྗͷςετΛ͢ΔͨΊʹεύΠΛ࢖͏
    ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ6TFS%FGBVMUTʹอଘ͢Δ
    େҬม਺΁ه࿥͍ͯ͠Δ

    View full-size slide

  46. class Output {
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }
    ҉໧తग़ྗͷςετΛ͢ΔͨΊʹεύΠΛ࢖͏
    ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ6TFS%FGBVMUTʹอଘ͢Δ
    େҬม਺΁ه࿥͍ͯ͠Δ
    ςετ࣌͸ผͷ৔ॴʹه࿥͍ͨ͠

    View full-size slide

  47. class Output {
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }
    ҉໧తग़ྗͷςετΛ͢ΔͨΊʹεύΠΛ࢖͏
    ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ6TFS%FGBVMUTʹอଘ͢Δ
    େҬม਺΁ه࿥͍ͯ͠Δ
    ςετ࣌͸ผͷ৔ॴʹه࿥͍ͨ͠
    εύΠΛ࢖͍͍ͨ

    View full-size slide

  48. class Output {
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }
    ҉໧తग़ྗͷςετΛ͢ΔͨΊʹεύΠΛ࢖͏
    ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ6TFS%FGBVMUTʹอଘ͢Δ
    େҬม਺΁ه࿥͍ͯ͠Δ
    ςετ࣌͸ผͷ৔ॴʹه࿥͍ͨ͠
    εύΠΛ࢖͍͍ͨ
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δʂ

    View full-size slide

  49. save(int:)
    Ҿ਺
    6TFS%FGBVMUT
    εύΠ
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    6TFS%FGBVMU΁௚઀ه࿥͸ͤͣʹɺ

    ݺͼग़͠΍มߋΛه࿥Ͱ͖ΔΦϒδΣΫτΛڬΉ

    View full-size slide

  50. εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶃه࿥͍ͨ͠ৼΔ෣͍Λ1SPUPDPMʹ͢Δ
    protocol WritableRepositoryContract {
    func write(int: Int)
    }

    View full-size slide

  51. εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶄ1SPUPDPMʹ४ڌͨ͠ΫϥεΛ࡞੒
    class WritableRepository: WritableRepositoryContract {
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: “write")
    }
    }

    View full-size slide

  52. ᶅ҉໧తग़ྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    class Output {
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }

    View full-size slide

  53. class Output {
    private let repository: WritableRepositoryContract
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తग़ྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ

    View full-size slide

  54. class Output {
    private let repository: WritableRepositoryContract
    init(repository: WritableRepositoryContract) {
    self.repository = repository
    }
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తग़ྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ

    View full-size slide

  55. class Output {
    private let repository: WritableRepositoryContract
    init(repository: WritableRepositoryContract) {
    self.repository = repository
    }
    func write(int: Int) {
    UserDefaults.standard.set(int, forKey: "write")
    }
    }
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తग़ྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ

    View full-size slide

  56. class Output {
    private let repository: WritableRepositoryContract
    init(repository: WritableRepositoryContract) {
    self.repository = repository
    }
    func write(int: Int) {
    self.repository.write(int: int)
    }
    }
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తग़ྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ

    View full-size slide

  57. class Output {
    private let repository: WritableRepositoryContract
    init(repository: WritableRepositoryContract) {
    self.repository = repository
    }
    func write(int: Int) {
    self.repository.write(int: int)
    }
    }
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తग़ྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ
    ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ6TFS%FGBVMUTʹอଘ͢Δ

    View full-size slide

  58. class Output {
    private let repository: WritableRepositoryContract
    init(repository: WritableRepositoryContract) {
    self.repository = repository
    }
    func write(int: Int) {
    self.repository.write(int: int)
    }
    }
    εύΠΛ࢖͑Δঢ়ଶʹ͢Δ
    ᶅ҉໧తग़ྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ
    ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ6TFS%FGBVMUTʹอଘ͢Δ
    ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ3FQPTJUPSZʹ౉͢

    View full-size slide

  59. εύΠΛ࢖͏४උ͸Ͱ͖ͨ

    View full-size slide

  60. εύΠΛ࢖ͬͯςετΛॻ͘
    εύΠΛ࢖͏४උ͸Ͱ͖ͨ

    View full-size slide

  61. εύΠΛ࢖ͬͯςετΛॻ͘
    1SPUPDPMʹ४ڌͨ͠εύΠΛ࡞੒͢Δ
    class WritableRepositorySpy: WritableRepositoryContract {
    /// ϝιου͕ݺͼग़͞ΕͨࡍͷҾ਺ྻɻ
    private(set) var callArguments: [Int] = []
    func write(int: Int) {
    self.record(int)
    }
    private func record(_ args: Int) {
    self.callArguments += [args]
    }
    }

    View full-size slide

  62. class WritableRepositorySpy: WritableRepositoryContract {
    /// ϝιου͕ݺͼग़͞ΕͨࡍͷҾ਺ྻɻ
    private(set) var callArguments: [Int] = []
    func write(int: Int) {
    self.record(int)
    }
    private func record(_ args: Int) {
    self.callArguments += [args]
    }
    }
    εύΠΛ࢖ͬͯςετΛॻ͘
    ϓϩτίϧ४ڌ
    1SPUPDPMʹ४ڌͨ͠εύΠΛ࡞੒͢Δ

    View full-size slide

  63. class WritableRepositorySpy: WritableRepositoryContract {
    /// ϝιου͕ݺͼग़͞ΕͨࡍͷҾ਺ྻɻ
    private(set) var callArguments: [Int] = []
    func write(int: Int) {
    self.record(int)
    }
    private func record(_ args: Int) {
    self.callArguments += [args]
    }
    }
    εύΠΛ࢖ͬͯςετΛॻ͘
    ݺͼग़͠Λه࿥͢Δ
    1SPUPDPMʹ४ڌͨ͠εύΠΛ࡞੒͢Δ

    View full-size slide

  64. εύΠΛ࢖ͬͯςετΛॻ͘
    ɾঢ়گJOUͷ࣌
    ˙ ςετέʔε
    ɾظ଴6TFS%FGBVMUT΁lz͕อଘ͞ΕΔ
    class OutputTests: XCTestCase {
    func testWrite() {
    let int = 2
    }
    }

    View full-size slide

  65. εύΠΛ࢖ͬͯςετΛॻ͘
    ɾঢ়گJOUͷ࣌
    ˙ ςετέʔε
    ɾظ଴6TFS%FGBVMUT΁lz͕อଘ͞ΕΔ
    class OutputTests: XCTestCase {
    func testWrite() {
    let int = 2
    let spy = WritableRepositorySpy()
    let output = Output(repository: spy)

    }
    }
    εύΠΛࠩ͠ࠐΉ

    View full-size slide

  66. εύΠΛ࢖ͬͯςετΛॻ͘
    ɾঢ়گJOUͷ࣌
    ˙ ςετέʔε
    ɾظ଴6TFS%FGBVMUT΁lz͕อଘ͞ΕΔ
    class OutputTests: XCTestCase {
    func testWrite() {
    let int = 2
    let spy = WritableRepositorySpy()
    let output = Output(repository: spy)

    output.write(int: int)
    XCTAssertEqual(int, spy.callArguments.first!)
    }
    }
    தͰεύΠ͕࢖ΘΕ͍ͯΔ

    View full-size slide

  67. εύΠΛ࢖ͬͯςετΛॻ͘
    ɾঢ়گJOUͷ࣌
    ˙ ςετέʔε
    ɾظ଴6TFS%FGBVMUT΁lz͕อଘ͞ΕΔ
    class OutputTests: XCTestCase {
    func testWrite() {
    let int = 2
    let spy = WritableRepositorySpy()
    let output = Output(repository: spy)

    output.write(int: int)
    XCTAssertEqual(int, spy.callArguments.first!)
    }
    }
    εύΠʹه࿥͞Εͨ஋Λ֬ೝ͢Δ

    View full-size slide

  68. ·ͱΊ
    ˙ ҉໧తೖग़ྗ͕͋Δ৔߹
    ɾೖྗ
    ɾِ෺ʹࠩ͠ସ͑ΒΕΔͱςετͷ४උָ͕ʹͳΔΑ
    ɾग़ྗ
    ɾʮ6TFS%FGBVMUTʹ΂ͬͨΓґଘʯͳΜͯ͜ͱ͕ແ͘ͳΔΑ
    ɾ1SPUPDPMΛ࢖ͬͯελϒ औಘ༻ͷِ෺
    Λ
    ɹࠩ͠ࠐΊΔΑ͏ʹ͠Α͏
    ɾ1SPUPDPMΛ࢖ͬͯεύΠ ه࿥༻ͷِ෺
    Λ
    ɹࠩ͠ࠐΊΔΑ͏ʹ͠Α͏
    ˙ ϝϦοτ

    View full-size slide

  69. &OKPZ5FTU%BZT

    View full-size slide