Upgrade to Pro — share decks privately, control downloads, hide ads and more …
Please sign in to continue.

不安定なテストは200種類あんねん

Avatar for yimajo yimajo
October 27, 2023

 不安定なテストは200種類あんねん

Avatar for yimajo

yimajo

October 27, 2023
Tweet

More Decks by yimajo

Other Decks in Programming

Transcript

  1. ݪҼͷ෼ྨ • େ෼ྨ1: ςετίʔυ·ͨ͸ςετର৅ͷϓϩμΫγϣϯίʔυ͕ѱ͍ • ݪҼ1: ࣮ߦ࣌ʹܾఆ͢Δಈతͳ஋ʹΑΔςετ࣮ߦ • ݪҼ2: OSSϑϨʔϜϫʔΫཧղෆ଍

    • ݪҼ3: ςετέʔεͷ࣮ߦॱংґଘ • ݪҼ4: ϓϩάϥϛϯάݴޠ/SDKͷཧղෆ଍ • ݪҼ ͦͷଞ • େ෼ྨ2: ςετ࣮ߦϚγϯཁҼʢ؀ڥʣ ࠓ೔࿩͢͜ͱ
  2. ྫ: Foundation.Date.init() / Foundation.Date.now • ͳͥෆ҆ఆ͞ʹͭͳ͕Δͷ͔ • ݻఆ஋Ͱ͸ͳ͍ͨΊ • ݱࡏ࣌ࠁͷ༻ҙ͔Βར༻͢Δ·Ͱ૝ఆ֎ʹ͕࣌ؒܦա͢Δ

    • ͲͷΑ͏ͳ৔߹ʹࠔΔͷ͔ • ςετର৅ͷϝιου಺ͰNඵҎ಺ͳͲͷॲཧ͕͋Δ • ςετίʔυࣗମͰ஋ͷൺֱʹ࢖͏ͷ΋΍͔͍ͬ • Ͳ͏ղܾ͢Δͷ͔ • Date.init()/Date.nowʹΑΔݱࡏ࣌ࠁऔಘ͸෭࡞༻࣮ߦͱߟ͑ɺDIͨ͠΋ͷΛར༻͢Δ • Ͱ͖Δ͚ͩݻఆ஋ʢfixtureʣΛ࢖͏ ෆ҆ఆͳݪҼ: ࣮ߦ࣌ʹܾఆ͢Δಈతͳ஋ʹΑΔςετ࣮ߦ
  3. ิ଍: ࣮ߦ࣌ʹಈతʹ஋͕ܾఆ͢Δ΍ͭΒ • Foundation.Date / Calendar / Locale / UUID

    • Swift Standard LibraryͷContinuousClock • ੔਺ͳͲͷཚ਺ੜ੒ ෆ҆ఆͳݪҼ: ࣮ߦ࣌ʹܾఆ͢Δಈతͳ஋ʹΑΔςετ࣮ߦ https://github.com/pointfreeco/swift-dependencies/tree/main/ Sources/Dependencies/DependencyValues ࢀߟ: pointfreeco/swift-dependencies
  4. class SpecA: QuickSpec { override class func spec() { describe("A")

    { print("A.describe") let date = Date() // beforeEachΛ࢖Θͳ͍ྫ it("actionϝιου͸1ඵҎ಺ʹ࣮ߦ͕׬ྃ͢Δ") { print("A.it") let subject = ... subject.action() expect(date - Date()) < 1.0 // ྫ } } } } class SpecB: QuickSpec { override class func spec() { describe(“B") { print("B.describe") it(“…”) { print("B.it") } } } } A.describe B.describe A.it B.it it͸࠷ޙʹ࣮ߦ͞ΕΔ • SpecAͷspecϝιου͕࣮ߦ͞ΕΔ • SpecAͷdescribe͕࣮ߦ͞ΕΔ • SpecBͷspecϝιου͕࣮ߦ͞ΕΔ • SpecBͷdescribe͕࣮ߦ͞ΕΔ • SpecAͷit͕࣮ߦ͞ΕΔ • SpecBͷit͕࣮ߦ͞ΕΔ print ݁Ռ
  5. XcodeͰͷςετ࣮ߦ (xcodebuild test ܥ) ͸ ϑΣʔζͱͯ͠ ςετͷ ొ࿥ ͱ ࣮ߦ

    ͷ2ϑΣʔζʹ ෼͔Ε͍ͯͯ Quick ͸ͦΕΛར༻͍ͯ͠Δɻ ςετొ࿥ϑΣʔζ ςετ࣮ߦϑΣʔζ XCTestCaseͷdefaultTestSuite XCTestCaseͷtestInvocations ิ଍BQQMFTXJGUUFTUJOHͰݱঢ়ςετొ࿥ͯ͠Δ΍Γํͱ΋ҧ͏
  6. XCTest Quick ϑΣʔζ1. Xcode͸XCTestCaseΛܧঝͨ͠Πϯελϯε͔ΒdefaultTestSuiteΛ࣮ߦ͢Δ ϑΣʔζ1_1. defaultTestSuite͔ΒgatherExamplesNeeded()͕ݺͼग़͞ΕΔ ϑΣʔζ1_2. gatherExamplesNeeded()͸spec()Λ࣮ߦ ϑΣʔζ1_3. spec()ʹ͋ΔbeforeEach()/it()ΛWorldʹappend͍ͯ͘͠

    ϑΣʔζ2. Xcode͸XCTestCaseܧঝ͍ͯ͠ΔΠϯελϯε͔ΒtestInvocationsΛ࣮ߦ͢Δ ϑΣʔζ2_1.testInvocations͸Worldʹappend͞ΕͯΔ΋ͷ͔ΒऔΓग़͠itΛςετͱ࣮ͯ͠ߦ beforeEach/it͸४උϑΣʔζͰอ࣋͞Ε ࣮ߦϑΣʔζͰ࣮ߦ͞ΕΔ
  7. ͓·͚: ৗʹࣦഊ͢Δྫ Presenter͕ղ์͞Ε݁Ռ͸ࣦഊɻ itΫϩʔδϟ͕࣮ߦ͞ΕΔ࣌͸ ϑΣʔζ2Ͱ͋ΓɺϑΣʔζ1Ͱ࡞੒ ͞ΕͨPresenter͸ࢀর͞Εͳ͍ͷ Ͱʢେ఍͸ʣղ์͞ΕΔ͜ͱͰdeinit ͕࣮ߦ͞Ε݁Ռ͕มΘΔɻ class SpecC:

    QuickSpec { override class func spec() { describe(“Presenter.viewDidLoad࣮ߦ”) { // ·ͨ΋΍beforeEach͠ͳ͍ let spy = View() let presenter = Presenter() // SUT presenter.view = spy // Action΋४උϑΣʔζͰ΍ͬͯ͠·͏ presenter.viewDidLoad() ɹɹ it("Viewͷ஋͕ViewDidLoadͰtrueʹͳͬͯΔ") { expect(spy.flag).to(beTrue()) // ݁Ռ͸ʁ } } } } class Presenter { var view: View? deinit { view?.flag = false } func viewDidLoad() { view?.flag = true } }
  8. ྫ: RxSwiftͰεέδϡʔϥΛDIͤͣςετͯ͠͠·͏ • ͳͥෆ҆ఆ͞ʹͭͳ͕Δͷ͔ • MainScheduler͸ಉظతʹ஋Λྲྀ͢ͱ͖΋͋Δ͠ඇಉظతʹ஋Λྲྀ ͢͜ͱ΋͋Δ • Ͳ͏ղܾ͢Δͷ͔ •

    εέδϡʔϥΛDI͠ςετεέδϡʔϥΛ࢖͏ • RxSwiftͷίʔυΛಡΉ͔RxSwiftݚڀಡຊΛങ͏ ෆ҆ఆͳݪҼ:OSSϑϨʔϜϫʔΫཧղෆ଍
  9. class SpecD: QuickSpec { override class func spec() { describe(“ະ੒೥൑ఆ͢Δ")

    { var subject = … var user = TestDouble.User() context(“৔ॴ͕೔ຊͰ10ࡀ”) { beforeEach { user.age = 10 subject.user = user } it("ະ੒೥൑ఆ͞ΕΔ") { subject.action() expect(subject.ະ੒೥).to(beTruth)) } } context(“৔ॴ͸ҟੈքͰ10ࡀ”) { beforeEach { user.age = 10 subject.user = user subject.location = .ҟੈք } it(“ະ੒೥൑ఆ͞Εͳ͍") { subject.action() expect(subject.ະ੒೥).to(beFalse)) } } ྫ: ্ͷ೔ຊcontextͰ͸locationΛ ઃఆ͍ͯ͠ͳ͍͕σϑΥϧτͷ locationͰઌʹςετ੒ޭ͠ɺ࣍ ʹԼͷҟੈքcontextͰ͸໌ࣔͯ͠ ςετ੒ޭ͍ͯ͠Δͱ͢Δɻ ઌʹԼͷҟੈքcontext͕࣮ߦ͞Ε Δͱ…?
  10. ྫ: ϝΠϯλʔήοτͰͷςετ͸ϗετΞϓϦέʔγϣϯ͕ىಈͯ͠͠·͏ • ͳͥෆ҆ఆ͞ʹͭͳ͕Δͷ͔ • ઃఆͱͯ͠ɺςετϞδϡʔϧΛϗετΞϓϦຊମ΁ͱࢦఆ͢Δͱςετ࣌ʹΞϓϦ͕ ىಈ͠ɺͦ͜Ͱ෭࡞༻Λ࣮ߦ͠ςετʹӨڹΛ༩͑Δ͜ͱ͕͋Δ • Ͳ͏ղܾ͢Δͷ͔ •

    AppDelegateΛMockͯ͠Կ΋͠ͳ͍ʢor Mockͤͣݕ஌͠෼ذͯ͠Կ΋͠ͳ͍ʣ • ϗετΞϓϦͷϞδϡʔϧ͸SwiftUI.App΍AppDelegateͷΈ࣋ͪɺͦΕҎ֎ͷॲཧ ͸Ϟδϡʔϧͱ͠෼ׂɺͦΕʹରͯ͠ςετλʔήοτϞδϡʔϧΛ࡞Δ • XcodeઃఆͰHost Application = Noneʹͯ͠ςετ࣮ߦͰ͖Ε͹͍͍ ෆ҆ఆͳݪҼ:ϓϩάϥϛϯάݴޠ/SDKͷཧղෆ଍
  11. ϝΠϯλʔήοτ ϝΠϯλʔήοτͷ ςετλʔήοτ )PTU"QQMJDBUJPOϝΠϯλʔήοτ ςετ࣮ߦͰ)PTU"QQMJDBUJPO͋ΔΜͰ ΞϓϦέʔγϣϯ͕ىಈ࣮ߦ͢Δɻ JNQPSU 1BDLBHFͷ ςετλʔήοτ λʔήοτ

    JNQPSU 1BDLBHFTXJGU JNQPSU YDXPSLTQBDF ิ଍YDPEFCVJMEͰͷςετͰ͋ΓTXJGUUFTU࣮ߦͰͷςετʹ͍ͭͯͷ࿩Ͱ͸͋Γ·ͤΜ &NCFEEFE'SBNFXPSL λʔήοτ &NCFEEFE.PEVMFͷ ςετλʔήοτ )PTU"QQMJDBUJPO/POF ςετ࣮ߦͰ)PTU"QQMJDBUJPO͕ͳ͍ͳΒɺ ΞϓϦέʔγϣϯ͸ىಈ࣮ߦ͠ͳ͍ɻ JNQPSU
  12. ྫ: XCTestCase.waitϝιουʹΑΓεϨου͕σουϩοΫ͢Δͱ͖͕͋Δ • ͳͥෆ҆ఆ͞ʹͭͳ͕Δͷ͔ • wait Ͱ Task { @MainActor

    in } ͷ݁ՌΛ଴ͭςετͳ৔߹ɺwait͸Ϗδʔ΢ΣΠτ͞ ͤͯϝΠϯεϨουΛࢭΊ͍ͯΔͨΊɺTaskͷϝΠϯεϨου࣮ߦΛ્֐͢Δ଴ͪ ͔ͨͱͳΓσουϩοΫ • Ͳ͏ղܾ͢Δͷ͔ • ͦ΋ͦ΋Xcode 14.3ܥͰ͸ܯࠂ͞ΕΔ • Swift ConcurrencyΛ࢖͏৔߹ fulfillment(of:timeout:…) ϝιου͕༻ҙ͞Ε͍ͯΔ ෆ҆ఆͳݪҼ:ϓϩάϥϛϯάݴޠ/SDKͷཧղෆ଍
  13. ׬