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
360
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
沖縄モバイルアプリ開発勉強会#1
tamaki
0
74
iOSアプリ開発を始めよう
tamaki
0
110
詳解xcresult.pdf
tamaki
0
280
メルペイでのリグレッションテスト自動化推進のこれまでとこれから
tamaki
0
660
What do you want to test with UI Test v2
tamaki
2
830
JPQRによって変わる日本のQRコード決済
tamaki
0
240
What's New in Testing
tamaki
1
58
What do you want to test with UI Test
tamaki
5
1.8k
How to control state in UI Test
tamaki
4
2.5k
Other Decks in Technology
See All in Technology
Assisted reorganization of data structures
ennael
PRO
0
210
Amazon BedrockとPR-Agentでコードレビュー自動化に挑戦・実際に運用してみた
diggymo
0
550
たった一人で始めた音楽制作が気がついたら会社公認の部活動になっていた話〜組織の垣根を超えるコラボレーションを実現するには〜 / On-KAG-bu
piyonakajima
0
150
Strict Concurrencyにしたらdeinitでクラッシュする話
0si43
0
120
普通の Web エンジニアのための様相論理入門 #yapcjapan / YAPC Hakodate 2024
ytaka23
2
390
XPを始める新人に伝えたい近道の鍵
nakasho
1
250
Oracle GoldenGate 23ai 導入Tips
oracle4engineer
PRO
1
200
AWS Lambdaで実現するスケーラブルで低コストなWebサービス構築/YAPC::Hakodate2024
fujiwara3
5
890
ORM と向き合う
hoto17296
7
5.9k
MLOpsの「あるある」課題の解決と、そのためのライブラリgokart
mski_iksm
1
150
DenoでもViteしたい!インポートパスのエイリアスを指定してラクラクアプリ開発
bengo4com
1
1.7k
C# 13 / .NET 9 の新機能 (RC 1 時点)
nenonaninu
1
1.1k
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
229
18k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
45
4.9k
From Idea to $5000 a Month in 5 Months
shpigford
380
46k
Documentation Writing (for coders)
carmenintech
65
4.3k
Designing with Data
zakiwarfel
98
5.1k
Making Projects Easy
brettharned
114
5.8k
Bash Introduction
62gerente
608
210k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
355
29k
What's new in Ruby 2.0
geeforr
341
31k
For a Future-Friendly Web
brad_frost
174
9.3k
Visualization
eitanlees
143
15k
VelocityConf: Rendering Performance Case Studies
addyosmani
324
23k
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͏ͱΞϓϦؒແࢹͯ͠௨͕Ͱ͖·͢ɻ ϦδΣΫτϦεΫݱࡏௐࠪதɺ·ͨվΊͯ͠·͢ɻͯ࣍ ճ
Ҏ্