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

try! Swift Tokyo 2017 RejectCon: Quick + Lensを用いたテストの構造化

try! Swift Tokyo 2017 RejectCon: Quick + Lensを用いたテストの構造化

Takeshi Ihara

February 28, 2017
Tweet

More Decks by Takeshi Ihara

Other Decks in Programming

Transcript

  1. import Quick import Nimble class TableOfContentsSpec: QuickSpec { override func

    spec() { describe("the 'Documentation' directory") { it("has everything you need to get started") { let sections = Directory("Documentation").sections expect(sections).to( contain( "Organized Tests with Quick Examples and Example Groups" ) ) expect(sections).to(contain("Installing Quick")) } context("if it doesn't have what you're looking for") { it("needs to be updated") { let you = You(awesome: true) expect{you.submittedAnIssue}.toEventually(beTruthy()) } } } } }
  2. • describe • ςετέʔεͷάϧʔϐϯάͷͨΊͷϝιου • context • describeͱಉ༷ • ςετΛཧղ͠΍͘͢͢ΔͨΊʹ࢖͍෼͚Δ

    • it • ίʔυ͕ͲͷΑ͏ʹಈ࡞͢΂͖͔Λએݴ͢Δϝιου • XCTest ͷ test methods ͷΑ͏ͳ΋ͷ • beforeEach, afterEach • ֤ςετ͕࢝·Δલ/ऴΘͬͨޙʹ࣮ߦ͞ΕΔϝιου • XCTest ͷ setUp, tearDown ͷΑ͏ͳ΋ͷ
  3. struct User { let name: String let age: Int let

    sns: SNS var isStudent: Bool { return age >= 6 && age <= 15 } } struct SNS { let twitter: String? let github: String? }
  4. struct User { let name: String let age: Int let

    sns: SNS var isStudent: Bool { return age >= 6 && age <= 15 } } struct SNS { let twitter: String? let github: String? }
  5. class UserSpec: QuickSpec { override func spec() { describe("User") {

    var user: User! beforeEach { user = User(name: "Takeshi Ihara", age: 24, sns: SNS(twitter: nil, github: nil)) } describe("isStudent") { context("when age is 13") { beforeEach { user = User(name: "name", age: 13, sns: SNS(twitter: nil, github: nil)) } it("user is student") { expect(user.isStudent).to(beTrue()) } } context("when age is 5") { beforeEach { user = User(name: "name", age: 5, sns: SNS(twitter: nil, github: nil)) } it("user is not student") { expect(user.isStudent).to(beFalse()) } } context("when age is 17") { ... } } } } }
  6. class UserSpec: QuickSpec { override func spec() { describe("User") {

    var user: User! beforeEach { user = User(name: "Takeshi Ihara", age: 24, sns: SNS(twitter: nil, github: nil)) } describe("isStudent") { context("when age is 13") { beforeEach { user = User(name: "name", age: 13, sns: SNS(twitter: nil, github: nil)) } it("user is student") { expect(user.isStudent).to(beTrue()) } } context("when age is 5") { beforeEach { user = User(name: "name", age: 5, sns: SNS(twitter: nil, github: nil)) } it("user is not student") { expect(user.isStudent).to(beFalse()) } } context("when age is 17") { ... } } } } } ςετର৅ લఏͷঢ়گ ظ଴͢Δ݁Ռ લఏͷঢ়گͷ࣮૷
  7. beforeEach context("when age is 13") { beforeEach { user =

    User( name: "name", age: 13, sns: SNS(twitter: nil, github: nil) ) } it("user is student") { expect(user.isStudent).to(beTrue()) } } ςετͷલఏঢ়گ͕ෆ໌֬
  8. struct Lens<A, B> { fileprivate let getter: (A) -> B

    fileprivate let setter: (A, B) -> A init(getter: @escaping (A) -> B, setter: @escaping (A, B) -> A) { self.getter = getter self.setter = setter } } extension Lens { func get(_ from: A) -> B { return getter(from) } func set(_ from: A, _ to: B) -> A { return setter(from, to) } func modify(_ from: A, f: (B) -> B) -> A { return set(from, f(get(from))) } }
  9. extension User { static var _name: Lens<User, String> { return

    Lens( getter: { $0.name }, setter: { User(name: $1, age: $0.age, sns: $0.sns) } ) } static var _age: Lens<User, Int> { return Lens( getter: { $0.age }, setter: { User(name: $0.name, age: $1, sns: $0.sns) } ) } static var _sns: Lens<User, SNS> { return Lens( getter: { $0.sns }, setter: { User(name: $0.name, age: $0.age, sns: $1) } ) } }
  10. class UserSpec: QuickSpec { override func spec() { describe("User") {

    var user: User! beforeEach { user = User(name: "Takeshi Ihara", age: 24, sns: SNS(twitter: nil, github: nil)) } describe("isStudent") { context("when age is 13") { beforeEach { user = User._age.set(user, 13) } it("user is student") { expect(user.isStudent).to(beTrue()) } } context("when age is 5") { beforeEach { user = User(name: "name", age: 5, sns: SNS(twitter: nil, github: nil)) } it("user is not student") { expect(user.isStudent).to(beFalse()) } } context("when age is 17") { ... } } } } } ςετʹؔ܎͢ΔQSPQFSUZ͚ͩ ઃఆͰ͖Δ