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

ソースコードから読み解く - Quick はどのように実装されているのか?/quick-c...

ソースコードから読み解く - Quick はどのように実装されているのか?/quick-code-reading

俺コン 2018 Summer / Day. 1
https://orecon.connpass.com/event/94858/

Yusuke Hosonuma

September 12, 2018
Tweet

More Decks by Yusuke Hosonuma

Other Decks in Programming

Transcript

  1. :VTVLF)PTPOVNB • ॴଐ ⁃ %F/"ɹ48&5άϧʔϓɹςετج൫νʔϜ • 'BWPSJUF ⁃  •

    ۙگ ⁃ J04%$Ͱ෼ൃද ⁃ ੔ମ͸͍͍ͧʂ Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 3 @tobi462ʢτϏʣ Swift 4.2
  2. :VTVLF)PTPOVNB • ॴଐ ⁃ %F/"ɹ48&5άϧʔϓɹςετج൫νʔϜ • 'BWPSJUF ⁃  •

    ۙگ ⁃ J04%$Ͱ෼ൃද ⁃ ੔ମ͸͍͍ͧʂ Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 4 @tobi462ʢτϏʣ Swift 4.2 ݄ࠒʹ։࠵ʁ
  3. 8 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. #%%ϑϨʔϜϫʔΫ 4XJGUൃදͷ೔ޙʹ044ެ։

    9$5FTUͱ౷߹ • ςετφϏήʔλͰදࣔ • Τϥʔϝοηʔδ΋ͪΌΜͱग़Δ Quick 34QFDΠϯεύΠΞ
  4. 11 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. import XCTest

    import Quick import Nimble class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } }
  5. 12 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. import XCTest

    import Quick import Nimble class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ςετߏ଄Խͱͯ͠ͷ2VJDL
  6. 13 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. import XCTest

    import Quick import Nimble class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } Ξαʔγϣϯͱͯ͠ͷ/JNCMF
  7. 17 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Τϥʔ͕ΤσΟλʹදࣔ Xcode

    Quick ͸Α͘Ͱ͖ͯΔͳ͊ Swift ΫϩʔδϟʹΑΔ DSL ΋ૉఢͩ
  8. ࿩͢͜ͱ 27 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 2VJDL͕Ͳ͏΍࣮ͬͯݱ͞ΕͯΔ͔ʁ

    • 9$5FTUͱͷ౷߹ • %4- ࿩͞ͳ͍͜ͱ 2VJDL/JNCMFͷ࢖͍ํ /JNCMFͷ࢓૊Έ ϚϧνϓϥοτϑΥʔϜରԠͱ͔ Today ίʔυΛಡΈͭͭʂ ࡉ͔͍ͱ͜Ζ͸ׂѪ͍ͯ͘͠ʂ
  9. 28 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ίʔυϦʔσΟϯά͍ͯ͘͠ͱ͜Ζ 

    ΤϯτϦϙΠϯτ  %4-͔Βͷߏ଄ͷ૊Έཱͯ  9$5FTU͔Βͷݺͼग़͠
  10. 29 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ίʔυϦʔσΟϯά͍ͯ͘͠ͱ͜Ζ 

    ΤϯτϦϙΠϯτ  %4-͔Βͷߏ଄ͷ૊Έཱͯ  9$5FTU͔Βͷݺͼग़͠ Let’s Code Reading !
  11. 31 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 2VJDL /JNCMF

    9$5FTU 'PVOEBUJPO 0CKFDUJWF$3VOUJNFΛར༻ ར༻͸೚ҙ ϥΠϒϥϦͷؔ܎
  12. 32 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 2VJDL /JNCMF

    9$5FTU 'PVOEBUJPO ࠓ͔Βݟ͍ͯ͘ ϥΠϒϥϦͷؔ܎
  13. 34 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. import XCTest

    import Quick import Nimble class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } }
  14. 35 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. import XCTest

    import Quick import Nimble class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ࠓճͷαϯϓϧͷ4QFD
  15. 36 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. import XCTest

    import Quick import Nimble class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } Ͳ͔͜Βݺ͹Ε͍ͯΔ͔ʁ
  16. 37 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. import XCTest

    import Quick import Nimble class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ਌ΫϥεΛݟͯΈΔ
  17. 38 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. #import <XCTest/XCTest.h>

    @interface QuickSpec : XCTestCase - (void)spec; @property (class, nonatomic, readonly) QuickSpec *current; @end QuickSpec.h
  18. 39 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. #import <XCTest/XCTest.h>

    @interface QuickSpec : XCTestCase - (void)spec; @property (class, nonatomic, readonly) QuickSpec *current; @end QuickSpec.h ͍͖ͳΓ Objective-C ʂ Ͱ΋ɺ਺গͳ͍͏ͪͷ1ιʔε
  19. 40 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // QuickSpec.h

    #import <XCTest/XCTest.h> @interface QuickSpec : XCTestCase - (void)spec; @property (class, nonatomic, readonly) QuickSpec *current; @end 9$5FTU$BTFΛܧঝ͍ͯ͠Δ QuickSpec.h
  20. 41 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // QuickSpec.m

    @implementation QuickSpec + (void)initialize { [QuickConfiguration initialize]; World *world = [World sharedWorld]; [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ QuickSpec *spec = [self new]; @try { [spec spec]; } @catch (NSException *exception) { ... } [self testInvocations]; }]; } QuickSpec.m
  21. 42 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // QuickSpec.m

    @implementation QuickSpec + (void)initialize { [QuickConfiguration initialize]; World *world = [World sharedWorld]; [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ QuickSpec *spec = [self new]; @try { [spec spec]; } @catch (NSException *exception) { ... } [self testInvocations]; }]; } 0CKFDUJWF$3VOUJNFʹΫϥε͕ ϩʔυ͞Εͨͱ͖ʹݺͼग़͞ΕΔ QuickSpec.m
  22. 43 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // QuickSpec.m

    @implementation QuickSpec + (void)initialize { [QuickConfiguration initialize]; World *world = [World sharedWorld]; [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ QuickSpec *spec = [self new]; @try { [spec spec]; } @catch (NSException *exception) { ... } [self testInvocations]; }]; } 8PSMEͷ4JOHMFUPOΛऔಘ͠ ΫϩʔδϟΛ࣮ߦ͠Α͏ͱ͍ͯ͠Δ QuickSpec.m
  23. 44 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // QuickSpec.m

    @implementation QuickSpec + (void)initialize { [QuickConfiguration initialize]; World *world = [World sharedWorld]; [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ QuickSpec *spec = [self new]; @try { [spec spec]; } @catch (NSException *exception) { ... } [self testInvocations]; }]; } ͜͜Ͱࣗ਎ͷΠϯελϯεΛੜ੒ͯ͠ TQFDΛ࣮ߦ͍ͯ͠Δʂ QuickSpec.m
  24. 45 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // QuickSpec.m

    @implementation QuickSpec + (void)initialize { [QuickConfiguration initialize]; World *world = [World sharedWorld]; [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ QuickSpec *spec = [self new]; @try { [spec spec]; } @catch (NSException *exception) { ... } [self testInvocations]; }]; } ͜͜Ͱࣗ਎ͷΠϯελϯεΛੜ੒ͯ͠ TQFDΛ࣮ߦ͍ͯ͠Δʂ QuickSpec.m spec ͕ݺ͹ΕΔ࢓૊Έ͸ ͳΜͱͳ͘Θ͔ͬͨͧʂ
  25. 48 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift
  26. 49 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ߏ଄తʹ͸͜͏ͳͬͯΔ CalcSpec.swift beforeEach describe context it describe
  27. 50 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ߏ଄తʹ͸͜͏ͳͬͯΔ CalcSpec.swift beforeEach describe context it describe ॱ൪ʹݟ͍ͯ͘
  28. 51 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe
  29. 53 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. public func

    describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.describe(description, flags: flags, closure: closure) } public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.context(description, flags: flags, closure: closure) } public func beforeEach(_ closure: @escaping BeforeExampleClosure) { World.sharedWorld.beforeEach(closure) } DSL.swift
  30. 54 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. public func

    describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.describe(description, flags: flags, closure: closure) } public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.context(description, flags: flags, closure: closure) } public func beforeEach(_ closure: @escaping BeforeExampleClosure) { World.sharedWorld.beforeEach(closure) } ... 8PSMEͷγϯάϧτϯʹରͯ͠ ҕৡ͍ͯ͠Δ͚ͩ DSL.swift
  31. 55 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } World+DSL.swift
  32. 56 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } 8PSMEͷFYUFOTJPO World+DSL.swift
  33. 57 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } &YBNQMF(SPVQΛੜ੒ͯ͠ World+DSL.swift
  34. 58 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } ݱࡏͷ&YBNQMF(SPVQʹ௥Ճ͠ World+DSL.swift
  35. 59 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } ΫϩʔδϟΛ౉࣮ͯ͠ߦ͍ͯ͠Δʂ World+DSL.swift
  36. 60 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } World.swift
  37. 61 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } ୀආͯ͠ݱࡏͷ&YBNQMF(SPVQΛஔ͖׵͑ World.swift
  38. 62 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } ΫϩʔδϟΛ࣮ߦ͠ World.swift
  39. 63 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } ୀආͯͨ͠&YBNQMF(SPVQΛݩʹ໭͍ͯ͠Δ World.swift
  40. 64 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } ୀආͯͨ͠&YBNQMF(SPVQΛݩʹ໭͍ͯ͠Δ World.swift closure ͬͯͳΜ͚ͩͬʁ ͦ͏͍͑͹
  41. 65 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // World.swift

    final internal class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } }
  42. 66 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // World.swift

    final internal class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } EFTDSJCFͷத਎ͩʂ
  43. 67 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // World.swift

    final internal class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } EFTDSJCFͷத਎ͩʂ ͳΜͱͳ͘ݟ͖͑ͯͨͧʂ
  44. 70 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe
  45. 71 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. public func

    describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.describe(description, flags: flags, closure: closure) } public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.context(description, flags: flags, closure: closure) } public func beforeEach(_ closure: @escaping BeforeExampleClosure) { World.sharedWorld.beforeEach(closure) } DSL.swift
  46. 72 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. public func

    describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.describe(description, flags: flags, closure: closure) } public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.context(description, flags: flags, closure: closure) } public func beforeEach(_ closure: @escaping BeforeExampleClosure) { World.sharedWorld.beforeEach(closure) } DSL.swift ΍͸Γ8PSMEͷγϯάϧτϯʹରͯ͠ Ҡৡ͍ͯ͠Δ͚ͩ
  47. 73 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. public func

    describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.describe(description, flags: flags, closure: closure) } public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { World.sharedWorld.context(description, flags: flags, closure: closure) } public func beforeEach(_ closure: @escaping BeforeExampleClosure) { World.sharedWorld.beforeEach(closure) } DSL.swift ΍͸Γ8PSMEͷγϯάϧτϯʹରͯ͠ Ҡৡ͍ͯ͠Δ͚ͩ DSL ෦෼͸ શ෦͜ͷ࢓૊ͬΆ͍ͧʁ
  48. 74 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } World+DSL.swift
  49. 75 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } ݱࡏͷ&YBNQMF(SPVQͷ World+DSL.swift
  50. 76 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } IPPLTʹΫϩʔδϟΛ௥Ճͯ͠Δ World+DSL.swift
  51. 77 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } // ExampleGroup.swift final public class ExampleGroup: NSObject { internal let hooks = ExampleHooks() } // ExampleHooks.swift final internal class ExampleHooks { internal var befores: [BeforeExampleWithMetadataClosure] = [] internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { befores.append { (_: ExampleMetadata) in closure() } } } ExampleGroup.swift / ExampleHooks.swift
  52. 78 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } // ExampleGroup.swift final public class ExampleGroup: NSObject { internal let hooks = ExampleHooks() } // ExampleHooks.swift final internal class ExampleHooks { internal var befores: [BeforeExampleWithMetadataClosure] = [] internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { befores.append { (_: ExampleMetadata) in closure() } } } ExampleGroup.swift / ExampleHooks.swift
  53. 79 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } // ExampleGroup.swift final public class ExampleGroup: NSObject { internal let hooks = ExampleHooks() } // ExampleHooks.swift final internal class ExampleHooks { internal var befores: [BeforeExampleWithMetadataClosure] = [] internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { befores.append { (_: ExampleMetadata) in closure() } } } ഑ྻʹΫϩʔδϟΛBQQFOEͯ͠Δ ExampleGroup.swift / ExampleHooks.swift
  54. 80 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } // ExampleGroup.swift final public class ExampleGroup: NSObject { internal let hooks = ExampleHooks() } // ExampleHooks.swift final internal class ExampleHooks { internal var befores: [BeforeExampleWithMetadataClosure] = [] internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { befores.append { (_: ExampleMetadata) in closure() } } } ഑ྻʹΫϩʔδϟΛBQQFOEͯ͠Δ ExampleGroup.swift / ExampleHooks.swift currentExampleGropup ͕ ͳΜ͔ͩϙΠϯτΈ͍ͨͧʁ
  55. 81 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } World+DSL.swift
  56. 82 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } // World.swift final internal class World: _WorldBase { internal var currentExampleGroup: ExampleGroup! internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } World+DSL.swift / World.swift
  57. 83 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } // World.swift final internal class World: _WorldBase { internal var currentExampleGroup: ExampleGroup! internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } 8PSME͕͍࣋ͬͯͯ World+DSL.swift / World.swift
  58. 84 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } // World.swift final internal class World: _WorldBase { internal var currentExampleGroup: ExampleGroup! internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } ͖ͬ͞Ұ࣌ୀආͯͨ͠΍ͭͩʂ World+DSL.swift / World.swift
  59. 85 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { guard currentExampleMetadata == nil else { raiseError("...") } currentExampleGroup.hooks.appendBefore(closure) } } // World.swift final internal class World: _WorldBase { internal var currentExampleGroup: ExampleGroup! internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } ͖ͬ͞Ұ࣌ୀආͯͨ͠΍ͭͩʂ World+DSL.swift / World.swift ͳΜ͔ͩͭͳ͕͖ͬͯͨͧʁ
  60. 86 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ͜͜·Ͱग़͖ͯͨιʔε CalcSpec.swift

    QuickSpec.h / m World+DSL.swift World.swift ExampleGroup.swift ExampleHooks.swift
  61. 88 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ͖ͬ͞ݟͨ΍ͭ
  62. 89 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } ࠶ܝ World+DSL.swift
  63. 90 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } ৽͍͠&YBNQMF(SPVQΛੜ੒ͯ͠ ݱࡏͷ&YBNQMF(SPVQʹ௥Ճ World+DSL.swift
  64. 91 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } ৽͍͠&YBNQMF(SPVQΛੜ੒ͯ͠ ݱࡏͷ&YBNQMF(SPVQʹ௥Ճ World+DSL.swift ExampleGroup ͬͯ describe ͷ͜ͱͰ͸ʁ
  65. 92 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } }
  66. 93 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } lBEEz ੜ੒ͯ͠Δͷ͸ࠓճͷEFTDSJCFͰ
  67. 94 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } લճͷ͕DVSSFOU&YBNQMF(SPVQͰ
  68. 95 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ৽͍͠ͷΛ௥Ճͯ͠
  69. 96 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ΫϩʔδϟΛ౉ͯ͠ॲཧͯ͠Δʂ
  70. 97 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // World+DSL.swift

    extension World { internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { let group = ExampleGroup(description: description, flags: flags) currentExampleGroup.appendExampleGroup(group) performWithCurrentExampleGroup(group, closure: closure) } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ΫϩʔδϟΛ౉ͯ͠ॲཧͯ͠Δʂ DSL ߏ଄͕૊ΈཱͯΒΕΔ ࢓૊Έ͕ݟ͖͑ͯͨͧʂ
  71. 98 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } World.swift
  72. 99 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } ྫͷҰ࣌ୀආͯͨ͠ίʔυ World.swift
  73. 100 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } ͖ͬ͞࡞ͬͨ&YBNQMF(SPVQͱ த਎ͷΫϩʔδϟ͕Ҿ਺ʹ World.swift
  74. 101 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } World currentExampleGroup ݱࡏͷ&YBNQMF(SPVQΛ World.swift
  75. 102 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } World currentExampleGroup ৽͍͠ͷʹ੾Γସ͑ͯ World.swift
  76. 103 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } ΫϩʔδϟΛධՁ͠ World currentExampleGroup World.swift
  77. 104 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. final internal

    class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } World currentExampleGroup ݩʹ໭͍ͯ͠Δʂ World.swift
  78. 105 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // World.swift

    final internal class World: _WorldBase { internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { let previousExampleGroup = currentExampleGroup currentExampleGroup = group closure() currentExampleGroup = previousExampleGroup } } class CalcSpec: QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } World currentExampleGroup ݩʹ໭͍ͯ͠Δʂ World.swift ͜Ε͕୯ͳΔؔ਺ʴΫϩʔδϟͰ ঢ়ଶΛอ࣋ͭͭ͠૊ΈཱͯΔ࢓૊Έ 8PSME͕ίϯςΩετΛ੾Γସ͍͑ͯ͘
  79. 106 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ͜͜·Ͱग़͖ͯͨιʔε CalcSpec.swift

    QuickSpec.h / m World+DSL.swift World.swift ExampleGroup.swift ExampleHooks.swift
  80. 108 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe
  81. 109 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func context(_ description: String, flags: FilterFlags, closure: () -> Void) { guard currentExampleMetadata == nil else { raiseError("...") } self.describe(description, flags: flags, closure: closure) } } World+DSL.swift
  82. 110 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func context(_ description: String, flags: FilterFlags, closure: () -> Void) { guard currentExampleMetadata == nil else { raiseError("...") } self.describe(description, flags: flags, closure: closure) } } EFTDSJCFΛݺΜͰΔ͚ͩ World+DSL.swift
  83. 111 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { internal func context(_ description: String, flags: FilterFlags, closure: () -> Void) { guard currentExampleMetadata == nil else { raiseError("...") } self.describe(description, flags: flags, closure: closure) } } EFTDSJCFΛݺΜͰΔ͚ͩ World+DSL.swift describe = context = ExampleGroup %4-ͱ໊ͯ͠લ͕ఏڙ͞Ε͍ͯΔ͚ͩ ࣮ଶ͸
  84. 113 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } ࠷ޙʂ CalcSpec.swift beforeEach describe context it describe
  85. 114 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. public func

    it(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { World.sharedWorld.it(description, flags: flags, file: file, line: line, closure: closure) } DSL.swift
  86. 115 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. public func

    it(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { World.sharedWorld.it(description, flags: flags, file: file, line: line, closure: closure) } ϚΫϩͰʮϑΝΠϧʯͱʮߦʯΛड͚औΓ DSL.swift
  87. 116 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. public func

    it(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { World.sharedWorld.it(description, flags: flags, file: file, line: line, closure: closure) } ͍ͭ΋ͷΑ͏ʹ8PSMEʹҕৡ DSL.swift
  88. 117 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { @nonobjc internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { let callsite = Callsite(file: file, line: line) let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) currentExampleGroup.appendExample(example) } } World+DSL.swift
  89. 118 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { @nonobjc internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { let callsite = Callsite(file: file, line: line) let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) currentExampleGroup.appendExample(example) } } ϑΝΠϧͱߦΛߏ଄ମʹϥοϓ͠ World+DSL.swift
  90. 119 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { @nonobjc internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { let callsite = Callsite(file: file, line: line) let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) currentExampleGroup.appendExample(example) } } &YBNQMFΛੜ੒͠ World+DSL.swift
  91. 120 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. extension World

    { @nonobjc internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { let callsite = Callsite(file: file, line: line) let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) currentExampleGroup.appendExample(example) } } DVSSFOU&YBNQMF(SPVQʹ௥Ճ World+DSL.swift
  92. 121 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // World+DSL.swift

    extension World { @nonobjc internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { let callsite = Callsite(file: file, line: line) let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) currentExampleGroup.appendExample(example) } } DVSSFOU&YBNQMF(SPVQʹ௥Ճ Έͳ·Ͱݴ͏ͳ ΋͏෼͔͍ͬͯΔ
  93. 122 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. // World+DSL.swift

    extension World { @nonobjc internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { let callsite = Callsite(file: file, line: line) let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) currentExampleGroup.appendExample(example) } } DVSSFOU&YBNQMF(SPVQʹ௥Ճ it = Example ͩʂ ಡΊΔɺಡΊΔͧʂ
  94. 124 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe
  95. 125 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ΦϒδΣΫτͷߏ଄͕ ݟ͖͑ͯͨͧ
  96. 126 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ExampleGroup: calc EFTDSJCF͸&YBNQMF(SPVQ
  97. 127 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ExampleGroup: calc hooks.befores
  98. 128 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ExampleGroup: calc hooks.befores ExampleGroup: add
  99. 129 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ExampleGroup: calc hooks.befores ExampleGroup: add ExampleGroup: 1 + 1 DPOUFYU΋&YBNQMF(SPVQ
  100. 130 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ExampleGroup: calc hooks.befores ExampleGroup: add ExampleGroup: 1 + 1 Example: works JU͸&YBNQMF
  101. 131 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ExampleGroup: calc hooks.befores ExampleGroup: add ExampleGroup: 1 + 1 Example: works CallSite (file, line) expect(calc.add(1, 1)).to(equal(2)) ϑΝΠϧɾߦɺΞαʔγϣϯίʔυΛ࣋ͭ
  102. 132 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift beforeEach describe context it describe ExampleGroup: calc hooks.befores ExampleGroup: add ExampleGroup: 1 + 1 Example: works CallSite (file, line) expect(calc.add(1, 1)).to(equal(2)) ϑΝΠϧɾߦɺΞαʔγϣϯίʔυΛ࣋ͭ Quick ͷ DSL ׬શʹཧղͨ͠
  103. 134 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift
  104. 135 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift %4-ͷΤϯτϦϙΠϯτҎ֎͸ఆ͍ٛͯ͠ͳ͍
  105. 136 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. class CalcSpec:

    QuickSpec { override func spec() { describe("calc") { var calc: Calc! beforeEach { calc = Calc() } describe("add") { context("1 + 1") { it("works") { expect(calc.add(1, 1)).to(equal(2)) } } } } } } CalcSpec.swift %4-ͷΤϯτϦϙΠϯτҎ֎͸ఆ͍ٛͯ͠ͳ͍ ΤϯτϦϙΠϯτʹ ൿີ͕͋Δʹҧ͍ͳ͍ ΋͏Ұ౓ݟͯΈΔ
  106. 137 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (void)initialize { [QuickConfiguration initialize]; World *world = [World sharedWorld]; [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ QuickSpec *spec = [self new]; @try { [spec spec]; } @catch (NSException *exception) { ... } [self testInvocations]; }]; } QuickSpec.m
  107. 138 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (void)initialize { [QuickConfiguration initialize]; World *world = [World sharedWorld]; [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ QuickSpec *spec = [self new]; @try { [spec spec]; } @catch (NSException *exception) { ... } [self testInvocations]; }]; } TQFD͕ݺ͹ΕͨޙͰ QuickSpec.m
  108. 139 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (void)initialize { [QuickConfiguration initialize]; World *world = [World sharedWorld]; [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ QuickSpec *spec = [self new]; @try { [spec spec]; } @catch (NSException *exception) { ... } [self testInvocations]; }]; } Կ͔ݺΜͰΔʂ QuickSpec.m
  109. 140 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } QuickSpec.m
  110. 141 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } JUʹରԠ͢Δ&YBNQMFΛநग़ͯ͠ QuickSpec.m
  111. 142 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } &YBNQMFΛΠϯελϯεϝιουʹ௥Ճͯ͠ QuickSpec.m
  112. 143 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } 4FMFDUPS͔Β/4*OWPDBUJPOΛੜ੒ͯ͠ QuickSpec.m
  113. 144 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } ͦͷҰཡΛฦͯ͠Δʂ QuickSpec.m
  114. 145 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } ͦͷҰཡΛฦͯ͠Δʂ QuickSpec.m Selector ͸෼͔Δ͚Ͳ NSInvocation ͬͯԿͩʁ TFMFDUPSͱ͔Ͱ
  115. 146 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. NSInvocation ϝοηʔδϯάΛදݱͨ͠ΦϒδΣΫτ

    0CKFDUJWF$3VOUJNFݶఆͷػೳ ଞݴޠͰݴ͑͹ʮϦϑϨΫγϣϯʯʹ͍ۙ 0CKFDUJWF$ʹ͓͚Δϝιουݺͼग़͠
  116. 147 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. NSInvocation ϝοηʔδϯάΛදݱͨ͠ΦϒδΣΫτ

    0CKFDUJWF$3VOUJNFݶఆͷػೳ ଞݴޠͰݴ͑͹ʮϦϑϨΫγϣϯʯʹ͍ۙ 0CKFDUJWF$ʹ͓͚Δϝιουݺͼग़͠ Dog walk(time: Time) NSInvocation XBML
  117. 148 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. NSInvocation ϝοηʔδϯάΛදݱͨ͠ΦϒδΣΫτ

    0CKFDUJWF$3VOUJNFݶఆͷػೳ ଞݴޠͰݴ͑͹ʮϦϑϨΫγϣϯʯʹ͍ۙ 0CKFDUJWF$ʹ͓͚Δϝιουݺͼग़͠ Dog walk(time: Time) NSInvocation XBML ίϯύΠϧ࣌ʹ֬ఆͯ͠ͳ͍ ϝιου΋ಈతʹݺͼग़ͤΔʂ 0CKFDUJWF$Ͱ͸
  118. 149 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } QuickSpec.m
  119. 150 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } it("works") { expect(calc.add(1, 1)).to(equal(2)) } Example: works NSInvocation JUʹର͢Δݺͼग़͠Λੜ੒ͯ͠ฦͯ͠Δʂ QuickSpec.m
  120. 151 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. @implementation QuickSpec

    + (NSArray *)testInvocations { NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; NSMutableSet<NSString*> *selectorNames = [NSMutableSet set]; for (Example *example in examples) { SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = selector; [invocations addObject:invocation]; } return invocations; } it("works") { expect(calc.add(1, 1)).to(equal(2)) } Example: works NSInvocation JUʹର͢Δݺͼग़͠Λੜ੒ͯ͠ฦͯ͠Δʂ QuickSpec.m ͜Εͬͯ΋͔ͯ͠͠ ͋ͷҰཡʹରԠͯ͠Δʁ ͋Εʁ
  121. 158 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. + (NSArray

    *)testInvocations Ͱ ςετର৅ͷҰཡΛฦͤΔ࢓૊Έ 9$5FTU͸
  122. 168 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ·ͱΊ 2VJDL͕Ͳ͏ಈ͔͘ݟ͖ͯͨ

    • ΤϯτϦϙΠϯτ • %4-͔ΒΦϒδΣΫτߏ଄ͷੜ੒ • 9$5FTUʹςετର৅ҰཡΛ౉͢ 0CKFDUJWF$ϥϯλΠϜͷ׆༻ • Ϋϥεϩʔυ࣌ͷJOJUJBMJ[F • /4*OWPDBUJPOʹΑΔಈతϝοηʔδϯά 8PSME͕ίϯςΩετΛҡ࣋
  123. 169 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ·ͱΊ 2VJDL͕Ͳ͏ಈ͔͘ݟ͖ͯͨ

    • ΤϯτϦϙΠϯτɿTQFD  • %4-͔ΒΦϒδΣΫτߏ଄ͷੜ੒ • 8PSMEΛ࢖ͬͨίϯςΩετҡ࣋ • 9$5FTUʹςετର৅ҰཡΛฦ͢ 0CKFDUJWF$ϥϯλΠϜͷ׆༻ • Ϋϥεϩʔυ࣌ͷJOJUJBMJ[F • /4*OWPDBUJPOʹΑΔಈతϝοηʔδϯά ͋ͳͨ΋ࠓ೔͔Β Quick ίϯτϦϏϡʔλ ࢲ΋
  124. 171 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ॓୊ &YBNQMF࣮ߦ࣌ʹCFGPSF&BDI͕ॲཧ͞ΕΔ࢓૊Έ

    • BGUFS&BDI͸ʁ • CFGPSF4VJUF͸ʁ ςετ໊͸Ͳ͜Ͱઃఆ͞Ε͍ͯΔʁ /JNCMFͷΤϥʔ͕ਖ਼͍͠Ґஔʹදࣔ͞ΕΔ࢓૊Έ