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

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

ソースコードから読み解く - 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. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ιʔείʔυ͔ΒಡΈղ͘
    2VJDL͸ͲͷΑ͏ʹ
    ࣮૷͞Ε͍ͯΔͷ͔ʁ
    1
    Զίϯ 2018 Summer / Day. 1
    2018/09/12 (Wed)

    ࡉপ ༞հ@DeNA

    View full-size slide

  2. "CPVU
    2
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

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

    • ۙگ
    ⁃ J04%$Ͱ෼ൃද
    ⁃ ੔ମ͸͍͍ͧʂ
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    3
    @tobi462ʢτϏʣ
    Swift 4.2

    View full-size slide

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

    • ۙگ
    ⁃ J04%$Ͱ෼ൃද
    ⁃ ੔ମ͸͍͍ͧʂ
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    4
    @tobi462ʢτϏʣ
    Swift 4.2
    ݄ࠒʹ։࠵ʁ

    View full-size slide

  5. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    5
    $G1ݕࡧαʔϏε
    ϖϯΪϯଜ5FDIͰ࡞Γ·ͨ͠ʂ
    ൃදεϥΠυ΁ͷϦϯΫ

    View full-size slide

  6. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    6
    $G1ݕࡧαʔϏε
    ϖϯΪϯଜ5FDIͰ࡞Γ·ͨ͠ʂ
    ൃදεϥΠυ΁ͷϦϯΫ
    iosdc-cfps.penginmura.tech

    View full-size slide

  7. 2VJDL
    7
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  8. 8
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    #%%ϑϨʔϜϫʔΫ
    4XJGUൃදͷ೔ޙʹ044ެ։
    9$5FTUͱ౷߹
    • ςετφϏήʔλͰදࣔ
    • Τϥʔϝοηʔδ΋ͪΌΜͱग़Δ
    Quick
    34QFDΠϯεύΠΞ

    View full-size slide

  9. /JNCMF
    9
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  10. Nimble
    10
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ΞαʔγϣϯϥΠϒϥϦ
    .BUIDFS"1*
    2VJDL͔Β͸ಠཱ
    Nimble

    View full-size slide

  11. 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))
    }
    }
    }
    }
    }
    }

    View full-size slide

  12. 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

    View full-size slide

  13. 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

    View full-size slide

  14. 14
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    Xcode

    View full-size slide

  15. 15
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    φϏήʔλʹදࣔ
    Xcode

    View full-size slide

  16. 16
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ςετͱͯ͠ೝࣝ
    Xcode

    View full-size slide

  17. 17
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    Τϥʔ͕ΤσΟλʹදࣔ
    Xcode
    Quick ͸Α͘Ͱ͖ͯΔͳ͊
    Swift ΫϩʔδϟʹΑΔ DSL ΋ૉఢͩ

    View full-size slide

  18. ͱ͜ΖͰ
    18
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  19. 19
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    Α͘ߟ͑ͯΈΔͱ
    Ͳ͏΍࣮ͬͯݱ͞ΕͯΔΜͩΖ͏ʁ
    ͋ΒͨΊͯݟͯΈΔ

    View full-size slide

  20. 20
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  21. 21
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͳͥφϏήʔλʹJUʹରԠ͢Δ໊લ͕ʁ

    View full-size slide

  22. 22
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    UFTU9YYͬͯϝιου໊͡Όͳ͍͚Ͳʁ

    View full-size slide

  23. 23
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ؔ਺ͳͷʹͲ͏΍ͬͯ%4-ߏ଄Λอ࣋ʁ

    View full-size slide

  24. 24
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    Τϥʔ΋Ͳ͏΍ͬͯग़ͯ͠ΔΜͩʁ

    View full-size slide

  25. 25
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    Τϥʔ΋Ͳ͏΍ͬͯग़ͯ͠ΔΜͩʁ
    ෼͔Βͳ͍
    Զͨͪ͸งғؾͰ Quick Λॻ͍͍ͯΔ

    View full-size slide

  26. 5PEBZ
    26
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  27. ࿩͢͜ͱ
    27
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    2VJDL͕Ͳ͏΍࣮ͬͯݱ͞ΕͯΔ͔ʁ
    • 9$5FTUͱͷ౷߹
    • %4-
    ࿩͞ͳ͍͜ͱ
    2VJDL/JNCMFͷ࢖͍ํ
    /JNCMFͷ࢓૊Έ
    ϚϧνϓϥοτϑΥʔϜରԠͱ͔
    Today
    ίʔυΛಡΈͭͭʂ
    ࡉ͔͍ͱ͜Ζ͸ׂѪ͍ͯ͘͠ʂ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  30. ϥΠϒϥϦͷؔ܎
    30
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

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

    View full-size slide

  32. 32
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    2VJDL
    /JNCMF
    9$5FTU
    'PVOEBUJPO
    ࠓ͔Βݟ͍ͯ͘
    ϥΠϒϥϦͷؔ܎

    View full-size slide

  33. ΤϯτϦϙΠϯτ
    33
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  34. 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))
    }
    }
    }
    }
    }
    }

    View full-size slide

  35. 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

    View full-size slide

  36. 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))
    }
    }
    }
    }
    }
    }
    Ͳ͔͜Βݺ͹Ε͍ͯΔ͔ʁ

    View full-size slide

  37. 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))
    }
    }
    }
    }
    }
    }
    ਌ΫϥεΛݟͯΈΔ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  41. 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

    View full-size slide

  42. 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

    View full-size slide

  43. 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

    View full-size slide

  44. 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

    View full-size slide

  45. 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 ͕ݺ͹ΕΔ࢓૊Έ͸
    ͳΜͱͳ͘Θ͔ͬͨͧʂ

    View full-size slide

  46. 46
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͜͜·Ͱग़͖ͯͨιʔε
    CalcSpec.swift
    QuickSpec.h / m

    View full-size slide

  47. %4-ͷॲཧ
    47
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  48. 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

    View full-size slide

  49. 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

    View full-size slide

  50. 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
    ॱ൪ʹݟ͍ͯ͘

    View full-size slide

  51. 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

    View full-size slide

  52. EFTDSJCF
    52
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  53. 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

    View full-size slide

  54. 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

    View full-size slide

  55. 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

    View full-size slide

  56. 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

    View full-size slide

  57. 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

    View full-size slide

  58. 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

    View full-size slide

  59. 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

    View full-size slide

  60. 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

    View full-size slide

  61. 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

    View full-size slide

  62. 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

    View full-size slide

  63. 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

    View full-size slide

  64. 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
    ͬͯͳΜ͚ͩͬʁ
    ͦ͏͍͑͹

    View full-size slide

  65. 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))
    }
    }
    }
    }
    }
    }

    View full-size slide

  66. 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ͷத਎ͩʂ

    View full-size slide

  67. 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ͷத਎ͩʂ
    ͳΜͱͳ͘ݟ͖͑ͯͨͧʂ

    View full-size slide

  68. 68
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͜͜·Ͱग़͖ͯͨιʔε
    CalcSpec.swift
    QuickSpec.h / m
    World+DSL.swift
    World.swift

    View full-size slide

  69. CFGPSF&BDI
    69
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  70. 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

    View full-size slide

  71. 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

    View full-size slide

  72. 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ͷγϯάϧτϯʹରͯ͠
    Ҡৡ͍ͯ͠Δ͚ͩ

    View full-size slide

  73. 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 ෦෼͸
    શ෦͜ͷ࢓૊ͬΆ͍ͧʁ

    View full-size slide

  74. 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

    View full-size slide

  75. 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

    View full-size slide

  76. 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

    View full-size slide

  77. 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

    View full-size slide

  78. 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

    View full-size slide

  79. 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

    View full-size slide

  80. 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 ͕
    ͳΜ͔ͩϙΠϯτΈ͍ͨͧʁ

    View full-size slide

  81. 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

    View full-size slide

  82. 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

    View full-size slide

  83. 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

    View full-size slide

  84. 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

    View full-size slide

  85. 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
    ͳΜ͔ͩͭͳ͕͖ͬͯͨͧʁ

    View full-size slide

  86. 86
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͜͜·Ͱग़͖ͯͨιʔε
    CalcSpec.swift
    QuickSpec.h / m
    World+DSL.swift
    World.swift
    ExampleGroup.swift
    ExampleHooks.swift

    View full-size slide

  87. EFTDSJCF
    87
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ࠶ͼ

    View full-size slide

  88. 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
    ͖ͬ͞ݟͨ΍ͭ

    View full-size slide

  89. 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

    View full-size slide

  90. 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

    View full-size slide

  91. 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 ͷ͜ͱͰ͸ʁ

    View full-size slide

  92. 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))
    }
    }
    }
    }
    }
    }

    View full-size slide

  93. 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Ͱ

    View full-size slide

  94. 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Ͱ

    View full-size slide

  95. 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))
    }
    }
    }
    }
    }
    }
    ৽͍͠ͷΛ௥Ճͯ͠

    View full-size slide

  96. 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))
    }
    }
    }
    }
    }
    }
    ΫϩʔδϟΛ౉ͯ͠ॲཧͯ͠Δʂ

    View full-size slide

  97. 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 ߏ଄͕૊ΈཱͯΒΕΔ
    ࢓૊Έ͕ݟ͖͑ͯͨͧʂ

    View full-size slide

  98. 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

    View full-size slide

  99. 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

    View full-size slide

  100. 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

    View full-size slide

  101. 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

    View full-size slide

  102. 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

    View full-size slide

  103. 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

    View full-size slide

  104. 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

    View full-size slide

  105. 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͕ίϯςΩετΛ੾Γସ͍͑ͯ͘

    View full-size slide

  106. 106
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͜͜·Ͱग़͖ͯͨιʔε
    CalcSpec.swift
    QuickSpec.h / m
    World+DSL.swift
    World.swift
    ExampleGroup.swift
    ExampleHooks.swift

    View full-size slide

  107. DPOUFYU
    107
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  108. 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

    View full-size slide

  109. 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

    View full-size slide

  110. 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

    View full-size slide

  111. 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-ͱ໊ͯ͠લ͕ఏڙ͞Ε͍ͯΔ͚ͩ
    ࣮ଶ͸

    View full-size slide

  112. JU
    112
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    lͦΕz͕ݟ͑ͨΒɺऴΘΓɻ

    View full-size slide

  113. 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

    View full-size slide

  114. 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

    View full-size slide

  115. 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

    View full-size slide

  116. 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

    View full-size slide

  117. 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

    View full-size slide

  118. 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

    View full-size slide

  119. 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

    View full-size slide

  120. 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

    View full-size slide

  121. 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ʹ௥Ճ
    Έͳ·Ͱݴ͏ͳ
    ΋͏෼͔͍ͬͯΔ

    View full-size slide

  122. 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 ͩʂ
    ಡΊΔɺಡΊΔͧʂ

    View full-size slide

  123. %4-શମΛݟ௚͢
    123
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  124. 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

    View full-size slide

  125. 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
    ΦϒδΣΫτͷߏ଄͕
    ݟ͖͑ͯͨͧ

    View full-size slide

  126. 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

    View full-size slide

  127. 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

    View full-size slide

  128. 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

    View full-size slide

  129. 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

    View full-size slide

  130. 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

    View full-size slide

  131. 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))
    ϑΝΠϧɾߦɺΞαʔγϣϯίʔυΛ࣋ͭ

    View full-size slide

  132. 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
    ׬શʹཧղͨ͠

    View full-size slide

  133. 9$5FTU͔Βͷݺͼग़͠
    133
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  134. 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

    View full-size slide

  135. 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-ͷΤϯτϦϙΠϯτҎ֎͸ఆ͍ٛͯ͠ͳ͍

    View full-size slide

  136. 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-ͷΤϯτϦϙΠϯτҎ֎͸ఆ͍ٛͯ͠ͳ͍
    ΤϯτϦϙΠϯτʹ
    ൿີ͕͋Δʹҧ͍ͳ͍
    ΋͏Ұ౓ݟͯΈΔ

    View full-size slide

  137. 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

    View full-size slide

  138. 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

    View full-size slide

  139. 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

    View full-size slide

  140. 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 *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

    View full-size slide

  141. 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 *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

    View full-size slide

  142. 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 *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

    View full-size slide

  143. 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 *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

    View full-size slide

  144. 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 *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

    View full-size slide

  145. 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 *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ͱ͔Ͱ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  149. 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 *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

    View full-size slide

  150. 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 *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

    View full-size slide

  151. 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 *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
    ͜Εͬͯ΋͔ͯ͠͠
    ͋ͷҰཡʹରԠͯ͠Δʁ
    ͋Εʁ

    View full-size slide

  152. 152
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  153. 153
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͋ͷҰཡ

    View full-size slide

  154. 154
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͋ͷҰཡ
    ࢼ͠ʹσόοάͯ͠
    Selector ͷத਎Λ೷͍ͯΈΔ

    View full-size slide

  155. 155
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  156. 156
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  157. 157
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ׬શʹҰக

    View full-size slide

  158. 158
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    + (NSArray *)testInvocations Ͱ
    ςετର৅ͷҰཡΛฦͤΔ࢓૊Έ
    9$5FTU͸

    View full-size slide

  159. ͜͜·ͰͷྲྀΕΛৼΓฦΔ
    159
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  160. 160
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

  161. 161
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ΫϥεϩʔυʹΑΓࣗ਎͕ੜ੒͞Εͯ

    View full-size slide

  162. 162
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    TQFD
    ͕ݺͼग़͞ΕΔ

    View full-size slide

  163. 163
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    8PSMEͰίϯςΩετΛҡ࣋ͭͭ͠
    %4-ΛΦϒδΣΫτߏ଄ʹ૊Έཱͯ

    View full-size slide

  164. 164
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    &YBNQMFSVO΁ͷ/4*OWPDBUJPOΛ
    9$5FTU͔ΒͷίʔϧόοΫͰฦ͢

    View full-size slide

  165. 165
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͦͷҰཡ͕9$5FTUʹΑΓ࣮ߦ͞Ε
    ςετ݁Ռ͕φϏήʔλʹදࣔ͞ΕΔ

    View full-size slide

  166. 166
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ͦͷҰཡ͕9$5FTUʹΑΓ࣮ߦ͞Ε
    ςετ݁Ռ͕φϏήʔλʹදࣔ͞ΕΔ
    Quick
    ׬શʹཧղͨ͠

    View full-size slide

  167. ·ͱΊ
    167
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide

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

    View full-size slide

  169. 169
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ·ͱΊ
    2VJDL͕Ͳ͏ಈ͔͘ݟ͖ͯͨ
    • ΤϯτϦϙΠϯτɿTQFD

    • %4-͔ΒΦϒδΣΫτߏ଄ͷੜ੒
    • 8PSMEΛ࢖ͬͨίϯςΩετҡ࣋
    • 9$5FTUʹςετର৅ҰཡΛฦ͢
    0CKFDUJWF$ϥϯλΠϜͷ׆༻
    • Ϋϥεϩʔυ࣌ͷJOJUJBMJ[F
    • /4*OWPDBUJPOʹΑΔಈతϝοηʔδϯά
    ͋ͳͨ΋ࠓ೔͔Β
    Quick ίϯτϦϏϡʔλ
    ࢲ΋

    View full-size slide

  170. ॓୊
    170
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ࢲ΋ͪΌΜͱ΍Γ·͢

    View full-size slide

  171. 171
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
    ॓୊
    &YBNQMF࣮ߦ࣌ʹCFGPSF&BDI͕ॲཧ͞ΕΔ࢓૊Έ
    • BGUFS&BDI͸ʁ
    • CFGPSF4VJUF͸ʁ
    ςετ໊͸Ͳ͜Ͱઃఆ͞Ε͍ͯΔʁ
    /JNCMFͷΤϥʔ͕ਖ਼͍͠Ґஔʹදࣔ͞ΕΔ࢓૊Έ

    View full-size slide

  172. %JEZPVFOKPZ
    $PEFSFBEJOH
    172
    Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

    View full-size slide