Asynchronous Testing in XCTest

Db5cf21a75ebe2484b95ea9dec5f573b?s=47 Shingo Tamaki
December 21, 2018

Asynchronous Testing in XCTest

This document explain about asynchronous testing in XCTest

Db5cf21a75ebe2484b95ea9dec5f573b?s=128

Shingo Tamaki

December 21, 2018
Tweet

Transcript

  1. Asyncronous Testing in XCTest

  2. XCTestʹ͓͚Δඇಉظॲཧͷςετ ඇಉظͷςετͷͨΊʹXCTestExpectationͱXCTWaiter༻ҙ͞ Ε͍ͯ·͢ɻ XCTestExpectationͷfulfillͷ࣮ߦΛ࣋ͬͯඇಉظॲཧͷ׬ྃͱ͠ waitͰࢦఆͨ͠expectationͷ׬ྃʹ଴ػ͢Δͷ͕جຊతͳྲྀΕ Ͱ͢ɻ • XCTestExpectation • XCTWaiter

  3. XCTestExpectation func test_fetchPilot() { // 1.XCTestExpectationΛ࡞੒ let expectation = XCTestExpectation(description:

    "pilot") PilotApiClient.fetchPilot(of: "new_type") { (result) in switch result { case .success(let user): XCTAssert(user.name == "REI") case .failure(_): break } // 2.ඇಉظॲཧͷ࣮ߦϒϩοΫͰfulfillΛ࣮ߦ expectation.fulfill() } // 3.waitؔ਺ʹexpectationΛࢦఆ wait(for: [expectation], timeout: 2) //<- 1ඵະຬͰςετࣦഊ }
  4. XCTestExpectation • expectedFulfillmentCount • isInverted

  5. XCTestExpectation expectedFulfillmentCountʹճ਺Λࢦఆ͢Δͱࢦఆճ਺ҎԼ͸ λΠϜΞ΢τͰςετࣦഊͱ͞Ε·͢ɻ /// RadarAPIClient͔Β͸·ͣ1ඵޙʹɺͦͯͦ͠Ε͔Β5ඵޙʹίʔϧόοΫ͕ฦ͖ͬͯ·͢ɻ /// ෳ਺ճίʔϧόοΫ͕࣮ߦ͞ΕΔ఺Λߟྀͯ͠Έ·͠ΐ͏ ! let expectation

    = XCTestExpectation(description: "radar") expectation.expectedFulfillmentCount = 2 let here = MyLocation(latitude: 35.664584, longitude: 139.730852) RadarApiClient.observeEnemy(from: here) { [expectation] (result) in switch result { case .success(let enemies): XCTAssert(enemies.count > 0) case .failure(_): break } expectation.fulfill() } wait(for: [expectation], timeout: 10)
  6. XCTestExpectation isInvertedΛࢦఆ͢ΔͱfulfillΛ"࣮ߦ͞Εͳ͍৔߹"ʹςετ͕੒ ޭ͠·͢ɻ let expectation = XCTestExpectation(description: "inverted") expectation.isInverted =

    true // fulfill͕ى͖ͳ͔ͬͨ৔߹ʹςετ੒ޭͱ͢Δ wait(for: [expectation], timeout: 1)
  7. XCTWaiter

  8. XCTWaiter ͔͜͜Β͸XCTWaiterͷ࿩Λ͠·͢ɻ XCTWaiter͸waitϝιουͳͲͷΑ͏ͳඇಉظॲཧͷ׬ྃΛ଴ ͭͨΊͷॲཧʹ͍ͭͯͷػೳΛ୲౰͠·͢ɻ ྫ͑͹wait͸XCTWaiterDelegateͰఆٛ͞Ε͓ͯΓɺ XCTestCase͕͜Εʹ४ڌ͍ͯ͠·͢ɻ

  9. wait(or waitForExpectations) • ॲཧ׬ྃ࣌ʹಛఆͷॲཧΛ࣮ߦ͍ͨ͠৔߹ • ඇಉظॲཧͷλΠϜΞ΢τ͕ҟͳΔ৔߹ • ඇಉظॲཧͷऴྃॱ͕৚݅ͱͳΔ৔߹(enforceOrder)

  10. wait(or waitForExpectations) ॲཧ׬ྃ࣌ʹಛఆͷॲཧΛ࣮ߦ͍ͨ͠৔߹ let expectation = self.expectation(description: "waitExpectations") DispatchQueue.main.asyncAfter(deadline: .now()

    + 0.5) { expectation.fulfill() //fulfillͳͩ͠ͱ.timeoutWhileWaitingʹͳΔ } // ίʔϧόοΫͷҾ਺͸Error?Ͱ͋Γɺਖ਼ৗ࣌͸λΠϜΞ΢τ࣌͸XCTestError͕ฦ٫͞ΕΔ waitForExpectations(timeout: 1) { (error) in guard let error = error as? XCTestError else { return } switch error.code { case .failureWhileWaiting: print(" ! ࣦഊ࣌͸ͪ͜Β") //ਖ਼௚ίϨͷى͜͠ํ͕Θ͔ͬͯͳ͍ break case .timeoutWhileWaiting: print(" ! λΠϜΞ΢τͷ৔߹͸ͪ͜Β") } }
  11. wait(or waitForExpectations) ඇಉظॲཧͷλΠϜΞ΢τ͕ҟͳΔ৔߹ ҰͭͷwaitͰॲཧͤͣʹෳ਺ͷwaitΛ࢖͏ࣄͰλΠϜΞ΢τͷ࣌ ؒΛ෼͚Δ͜ͱ͕Ͱ͖Δɻ let expForPilot = XCTestExpectation(description: "pilot")

    fetchPilot(expForPilot) let expForColony = XCTestExpectation(description: "colony") fetchColony(expForColony) // λΠϜΞ΢τͷ͕࣌ؒҧ͏ͷͰ͋Ε͹waitؔ਺Λෳ਺ʹ෼͚࣮ͯߦ͢Δࣄ΋ग़དྷΔɻ wait(for: [expForPilot], timeout: 2) wait(for: [expForColony], timeout: 4)
  12. wait(or waitForExpectations) ಛఆͷॱ൪Λظ଴ͯ͠ςετ͢Δ৔߹enforceOrderΛtrueʹ͢ ΔࣄͰ࣮ߦ׬ྃॱग़ͳ͍৔߹ʹςετࣦഊͱ͢Δ͜ͱ͕Ͱ͖ Δɻ let expForPilot = XCTestExpectation(description: "pilot")

    let expForColony = XCTestExpectation(description: "colony") // ྫ͑͹fetchColonyͷޙʹfetchPilot͠ͳ͚Ε͹͍͚ͳ͍ཁ͕݅͋ͬͨ৔߹ fetchColony(expForColony) { fetchPilot(expForPilot) } wait(for: [expForColony, expForPilot], timeout: 10, enforceOrder: true) //<- enforceOrderΛࢦఆ͢ΔࣄͰexpectationͷॱং·ͰݟΔ͜ͱ͕Ͱ͖Δ
  13. ৭ʑͳExpectationୡ

  14. ৭ʑͳExpectationୡ • XCTKVOExpectation • XCTNSNotificationExpectation • XCTNSPredicateExpectation • XCTDarwinNotificationExpectation

  15. XCTKVOExpectation KVO(Key Value Observe)Λར༻ͨ͠Expectation KeyPathʹࢦఆͨ͠ϓϩύςΟͷ؂ࢹΛߦ͏ࣄͰར༻Մೳ let noobPilot = Pilot(id: "noob",

    name: "Arbeo", abilities: []) let battleField = BattleField(pilots: [noobPilot]) let expectation = XCTKVOExpectation(keyPath: "mind", object: noobPilot) battleField.startBattle() wait(for: [expectation], timeout: 3)
  16. XCTNSNotificationExpectation NSNotificationΛར༻ͨ͠Expectation ࢦఆ໊ͨ͠લͷ௨஌Λ࣋ͬͯ׬ྃͱ͢Δࣄ͕Ͱ͖Δɻ let noobPilot = Pilot(id: "noob", name: "Arbeo",

    abilities: []) let battleField = BattleField(pilots: [noobPilot]) let expectation = XCTNSNotificationExpectation(name: Notification.Name("΍ͬͯ΍Δʂ΍ͬͯ΍Δͧʂ")) battleField.startBattle() wait(for: [expectation], timeout: 3)
  17. XCTNSPredicateExpectation NSPredicateΛར༻ͨ͠Expectation ৚݅ʹ߹கΛॲཧ׬ྃͱ͢Δ͜ͱ͕Ͱ͖Δ let noobPilot = Pilot(id: "noob", name: "Arbeo",

    abilities: []) let battleField = BattleField(pilots: [noobPilot]) let predicate = NSPredicate(format: "mind == 1") let expectation = XCTNSPredicateExpectation(predicate: predicate, object: noobPilot) battleField.startBattle() wait(for: [expectation], timeout: 3)
  18. XCTDarwinNotificationExpectatio n Darwin NotificationΛར༻ͨ͠Expectation NSNotificationͱಉ͘͡ࢦఆ໊ͨ͠લͷ௨஌Λ࣋ͬͯ׬ྃͱ͢Δ ࣄ͕Ͱ͖Δɻ let noobPilot = Pilot(id:

    "noob", name: "Arbeo", abilities: []) let battleField = BattleField(pilots: [noobPilot]) let expectation = XCTDarwinNotificationExpectation(notificationName: "΍ͬͯΈΔ͞ʂ") battleField.startBattle() wait(for: [expectation], timeout: 3)
  19. ͓·͚ Darwin Notify࢖͏ͱΞϓϦؒແࢹͯ͠௨஌͕Ͱ͖·͢ɻ ϦδΣΫτϦεΫ͸ݱࡏௐࠪதɺ·ͨվΊͯ࿩͠·͢ɻ଴ͯ࣍ ճ

  20. Ҏ্