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

単体テストのハジメ

 単体テストのハジメ

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

830d824769dd94553ab4e9955765f967?s=128

yokoya-s000

July 26, 2017
Tweet

Transcript

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

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

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

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

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

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

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

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

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

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

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

    ྫ͑͹Ͳ͏͍͏ςετʁ
  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") } }
  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Λॳظঢ়ଶʹ͔ͯ͠Βελʔτ
  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ʹ௚઀ॻ͖ࠐΉ
  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ʹՃ͑ͨมߋΛऔΓফ͢
  16. ҉໧తͳೖग़ྗͷςετྫ ˙ 6TFS%FGBVMUTΛ௚઀৮Δͱ͕͜͜ਏ͍ ɾ༩͑ͨมߋΛফ͠๨ΕΔͱɺຊମ࣮ߦ࣌΍ଞͷςετʹӨڹ͢Δ ɾςετߦ͏ͱ΋Εͳ͘ ʮ6TFS%FGBVMUT΁ͷૢ࡞෭࡞༻ʯ͕ੜͯ͡͠·͏ ෭࡞༻ͳ͘ςετ͍ͨ͠ʂ

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

    εύΠͱ͍͏ख๏ Λ࢖͍·͢
  18. ҉໧తೖྗͷςετΛ ͢ΔͨΊʹελϒΛ࢖͏ ຊ୊ͦͷ̍

  19. doSomething(x) Ҿ਺ େҬม਺ͳͲ ࣄલʹઃఆͨ͠ৼΔ෣͍Λ͢Δ
 ِ෺ͷΦϒδΣΫτ ελϒ ໭Γ஋ ˞ࢲ͕͜Ε͔Βઆ໌͢ΔʮελϒʯͷৼΔ෣͍͸্هͷ΋ͷ ʹͳΓ·͢ ಉ໊ͰผͷఆٛΛࢦ͢͜ͱ΋͋ΔͨΊ

    ҉໧తೖྗͷςετΛ͢ΔͨΊʹελϒΛ࢖͏
  20. ҉໧తೖྗͷςετΛ͢ΔͨΊʹελϒΛ࢖͏ ˙ ཁ݅6TFS%FGBVMUT͔Βऔಘͨ͠஋ *OU  Ҿ਺໭Γ஋ class Input { func

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

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

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

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

    multiplication(int: Int) -> Int { let base = UserDefaults.standard.integer(forKey: “base") return base * int } ςετ࣌͸ِ෺ʹࠩ͠ସ͍͑ͨ ελϒΛ࢖͍͍ͨ ελϒΛ࢖͑Δঢ়ଶʹ͢Δʂ େҬม਺͔Βऔಘ͍ͯ͠Δ
  25. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ multiplication(int:) Ҿ਺ 6TFS%FGBVMUT ελϒ ໭Γ஋ 6TFS%FGBVMU͔Β௚઀औಘ͸ͤͣʹɺ
 ৼΔ෣͍Λ੍ޚͰ͖ΔΦϒδΣΫτΛڬΉ

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

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

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

    { let base = UserDefaults.standard.integer(forKey: “base") return base * int } }
  29. ελϒΛ࢖͑Δঢ়ଶʹ͢Δ class Input { private let repository: ReadableRepositoryContract func multiplication(int:

    Int) -> Int { let base = UserDefaults.standard.integer(forKey: “base") return base * int } } ᶅ҉໧తೖྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ
  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Λར༻͢ΔΑ͏ʹมߋ͢Δ
  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Λར༻͢ΔΑ͏ʹมߋ͢Δ
  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Λར༻͢ΔΑ͏ʹมߋ͢Δ
  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  Ҿ਺໭Γ஋
  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  Ҿ਺໭Γ஋
  35. ελϒΛ࢖͏४උ͸Ͱ͖ͨ

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

  37. ελϒΛ࢖ͬͯςετΛॻ͘ class ReadableRepositoryStub: ReadableRepositoryContract { private let base: Int init(base:

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

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

    5 let int = 2 let expected = 10 } } ˙ ςετέʔε ɾظ଴͕ฦͬͯ͘Δ ελϒΛ࢖ͬͯςετΛॻ͘ ɾঢ়گCBTF JOUͷ࣌
  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ͷ࣌ ˙ ςετέʔε ɾظ଴͕ฦͬͯ͘Δ ελϒΛ࢖ͬͯςετΛॻ͘ ελϒΛࠩ͠ࠐΉ
  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ͷ࣌ ˙ ςετέʔε ɾظ଴͕ฦͬͯ͘Δ ελϒΛ࢖ͬͯςετΛॻ͘ தͰελϒ͕࢖ΘΕ͍ͯΔ
  42. ελϒ׬

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

  44. doSomething(x) Ҿ਺ ໭Γ஋ େҬม਺ͳͲ ِ෺ͷؔ਺΍ΦϒδΣΫτͰɺ
 ݺͼग़͠΍ࣗ਎΁ͷมߋΛه࿥͢Δ εύΠ ҉໧తग़ྗͷςετΛ͢ΔͨΊʹεύΠΛ࢖͏

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

    UserDefaults.standard.set(int, forKey: "write") } }
  46. class Output { func write(int: Int) { UserDefaults.standard.set(int, forKey: "write")

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

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

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

    } } ҉໧తग़ྗͷςετΛ͢ΔͨΊʹεύΠΛ࢖͏ ˙ ཁ݅Ҿ਺Ͱड͚औͬͨ஋Λ6TFS%FGBVMUTʹอଘ͢Δ େҬม਺΁ه࿥͍ͯ͠Δ ςετ࣌͸ผͷ৔ॴʹه࿥͍ͨ͠ εύΠΛ࢖͍͍ͨ εύΠΛ࢖͑Δঢ়ଶʹ͢Δʂ
  50. save(int:) Ҿ਺ 6TFS%FGBVMUT εύΠ εύΠΛ࢖͑Δঢ়ଶʹ͢Δ 6TFS%FGBVMU΁௚઀ه࿥͸ͤͣʹɺ
 ݺͼग़͠΍มߋΛه࿥Ͱ͖ΔΦϒδΣΫτΛڬΉ

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

  52. εύΠΛ࢖͑Δঢ়ଶʹ͢Δ ᶄ1SPUPDPMʹ४ڌͨ͠ΫϥεΛ࡞੒ class WritableRepository: WritableRepositoryContract { func write(int: Int) {

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

    forKey: "write") } }
  54. class Output { private let repository: WritableRepositoryContract func write(int: Int)

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

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

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

    self.repository = repository } func write(int: Int) { self.repository.write(int: int) } } εύΠΛ࢖͑Δঢ়ଶʹ͢Δ ᶅ҉໧తग़ྗͷՕॴͰ͸1SPUPDPMΛར༻͢ΔΑ͏ʹมߋ͢Δ
  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ʹอଘ͢Δ
  59. 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ʹ౉͢
  60. εύΠΛ࢖͏४උ͸Ͱ͖ͨ

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

  62. εύΠΛ࢖ͬͯςετΛॻ͘ 1SPUPDPMʹ४ڌͨ͠εύΠΛ࡞੒͢Δ class WritableRepositorySpy: WritableRepositoryContract { /// ϝιου͕ݺͼग़͞ΕͨࡍͷҾ਺ྻɻ private(set) var

    callArguments: [Int] = [] func write(int: Int) { self.record(int) } private func record(_ args: Int) { self.callArguments += [args] } }
  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ʹ४ڌͨ͠εύΠΛ࡞੒͢Δ
  64. class WritableRepositorySpy: WritableRepositoryContract { /// ϝιου͕ݺͼग़͞ΕͨࡍͷҾ਺ྻɻ private(set) var callArguments: [Int]

    = [] func write(int: Int) { self.record(int) } private func record(_ args: Int) { self.callArguments += [args] } } εύΠΛ࢖ͬͯςετΛॻ͘ ݺͼग़͠Λه࿥͢Δ 1SPUPDPMʹ४ڌͨ͠εύΠΛ࡞੒͢Δ
  65. εύΠΛ࢖ͬͯςετΛॻ͘ ɾঢ়گJOUͷ࣌ ˙ ςετέʔε ɾظ଴6TFS%FGBVMUT΁lz͕อଘ͞ΕΔ class OutputTests: XCTestCase { func

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

    testWrite() { let int = 2 let spy = WritableRepositorySpy() let output = Output(repository: spy)
 } } εύΠΛࠩ͠ࠐΉ
  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!) } } தͰεύΠ͕࢖ΘΕ͍ͯΔ
  68. εύΠΛ࢖ͬͯςετΛॻ͘ ɾঢ়گ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!) } } εύΠʹه࿥͞Εͨ஋Λ֬ೝ͢Δ
  69. εύΠ׬

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

    ɹࠩ͠ࠐΊΔΑ͏ʹ͠Α͏ ɾ1SPUPDPMΛ࢖ͬͯεύΠ ه࿥༻ͷِ෺ Λ ɹࠩ͠ࠐΊΔΑ͏ʹ͠Α͏ ˙ ϝϦοτ
  71. &OKPZ5FTU%BZT