Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Asynchronous Testing in XCTest
Search
Shingo Tamaki
December 21, 2018
Technology
0
470
Asynchronous Testing in XCTest
This document explain about asynchronous testing in XCTest
Shingo Tamaki
December 21, 2018
Tweet
Share
More Decks by Shingo Tamaki
See All by Shingo Tamaki
Use Gemini CLI from Claude Code as part of Sub Agent
tamaki
0
270
Let's make an Immersive Video with APMP
tamaki
0
44
Firebase Studioで始めるモバイルアプリ開発入門
tamaki
0
37
Introduction to Claude Code Action
tamaki
0
760
AIエージェントを使ったiOSアプリ開発を試してみた
tamaki
0
180
沖縄モバイルアプリ開発勉強会#1
tamaki
0
140
iOSアプリ開発を始めよう
tamaki
0
230
詳解xcresult.pdf
tamaki
0
420
メルペイでのリグレッションテスト自動化推進のこれまでとこれから
tamaki
0
810
Other Decks in Technology
See All in Technology
2026年のAIエージェント構築はどうなる?
minorun365
9
1.5k
AIで 浮いた時間で 何をする? 2026春 #devsumi
konifar
15
2.3k
「OSアップデート:年に一度の「大仕事」を乗り切るQA戦略」_Mobile Tech Flex 〜4社合同!私たちのモバイル開発自慢大会〜
gu3
0
120
歴史に敬意を! パラシュートVPoEが組織と共同で立ち上がる信頼醸成オンボーディング
go0517go
PRO
0
110
30分でわかる「ネットワーク図の描き方入門」/infraengbooks56
corestate55
1
350
個人的3D Gaussian Splattingニュースをご紹介 / sharing 3d gaussian splatting news
drumath2237
0
270
Three-Legged OAuth in AgentCore Gateway
hironobuiga
1
120
新規事業開発でのAWS活用
amixedcolor
1
180
意外と知ってそうでしらない、Reserved Instances の世界
mappie_kochi
0
170
xDS を活用したサービスディスカバリーで実現するブランチ別 QA 環境の構築手法
knwoop
1
180
【Claude Code】Plugins作成から始まったファインディの開発フロー改革
starfish719
0
310
EMから現場に戻って見えた2026年の開発者視点
sudoakiy
1
250
Featured
See All Featured
How to Ace a Technical Interview
jacobian
281
24k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.8k
Deep Space Network (abreviated)
tonyrice
0
74
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
89
Practical Orchestrator
shlominoach
191
11k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Why Our Code Smells
bkeepers
PRO
340
58k
The Curious Case for Waylosing
cassininazir
0
250
Automating Front-end Workflow
addyosmani
1371
200k
So, you think you're a good person
axbom
PRO
2
1.9k
Building the Perfect Custom Keyboard
takai
2
700
The Limits of Empathy - UXLibs8
cassininazir
1
230
Transcript
Asyncronous Testing in XCTest
XCTestʹ͓͚Δඇಉظॲཧͷςετ ඇಉظͷςετͷͨΊʹXCTestExpectationͱXCTWaiter༻ҙ͞ Ε͍ͯ·͢ɻ XCTestExpectationͷfulfillͷ࣮ߦΛ࣋ͬͯඇಉظॲཧͷྃͱ͠ waitͰࢦఆͨ͠expectationͷྃʹػ͢Δͷ͕جຊతͳྲྀΕ Ͱ͢ɻ • XCTestExpectation • XCTWaiter
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ඵະຬͰςετࣦഊ }
XCTestExpectation • expectedFulfillmentCount • isInverted
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)
XCTestExpectation isInvertedΛࢦఆ͢ΔͱfulfillΛ"࣮ߦ͞Εͳ͍߹"ʹςετ͕ ޭ͠·͢ɻ let expectation = XCTestExpectation(description: "inverted") expectation.isInverted =
true // fulfill͕ى͖ͳ͔ͬͨ߹ʹςετޭͱ͢Δ wait(for: [expectation], timeout: 1)
XCTWaiter
XCTWaiter ͔͜͜ΒXCTWaiterͷΛ͠·͢ɻ XCTWaiterwaitϝιουͳͲͷΑ͏ͳඇಉظॲཧͷྃΛ ͭͨΊͷॲཧʹ͍ͭͯͷػೳΛ୲͠·͢ɻ ྫ͑waitXCTWaiterDelegateͰఆٛ͞Ε͓ͯΓɺ XCTestCase͕͜Εʹ४ڌ͍ͯ͠·͢ɻ
wait(or waitForExpectations) • ॲཧྃ࣌ʹಛఆͷॲཧΛ࣮ߦ͍ͨ͠߹ • ඇಉظॲཧͷλΠϜΞτ͕ҟͳΔ߹ • ඇಉظॲཧͷऴྃॱ͕݅ͱͳΔ߹(enforceOrder)
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(" ! λΠϜΞτͷ߹ͪ͜Β") } }
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)
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ͷॱং·ͰݟΔ͜ͱ͕Ͱ͖Δ
৭ʑͳExpectationୡ
৭ʑͳExpectationୡ • XCTKVOExpectation • XCTNSNotificationExpectation • XCTNSPredicateExpectation • XCTDarwinNotificationExpectation
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)
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)
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)
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)
͓·͚ Darwin Notify͏ͱΞϓϦؒແࢹͯ͠௨͕Ͱ͖·͢ɻ ϦδΣΫτϦεΫݱࡏௐࠪதɺ·ͨվΊͯ͠·͢ɻͯ࣍ ճ
Ҏ্