Slide 1

Slide 1 text

Cloud Firestore を 作ってみた 2017/12/08 Mobile Act OSAKA #2 の、スタブ

Slide 2

Slide 2 text

About Me • Twitter、GitHub、Qiita、
 SlideShare、Speaker Deck: ➡ hironytic • At work: ➡ iOS (Objective-C)、
 ときどき Android (Java)、
 Windows UWP(C#) • At home: ➡ iOS (Swift) ひろん
 (一宮 浩教)

Slide 3

Slide 3 text

Firebase •Remote Config •App Indexing •Dynamic Links •Invites •AdWords •AdMob •Analytics Develop Grow Earn •Cloud Messaging •Authentication •Realtime Database •Cloud Firestore (beta) •Storage •Hosting •Test Lab •Crash Reporting Oct.4, 2017
 Mobile Act OSAKA #1

Slide 4

Slide 4 text

Cloud Firestore リアルタイムなデータ取得 サーバーとの通信も全部面倒見てくれる 使っている部分のテストどうしよう

Slide 5

Slide 5 text

そうだ スタブ、作ろう

Slide 6

Slide 6 text

スタブろう • スタブ (stub) とは、コンピュータプログラム のモジュールをテストする際、そのモジュール が呼び出す下位モジュールの代わりに用いる代 用品のこと。 引用元:Wikipedia 【スタブ】

Slide 7

Slide 7 text

ドキュメント • JSONライクなKey-Value • Swiftでは [String: Any] { "name": "Nobita", "skill": "Hirune" }

Slide 8

Slide 8 text

コレクション • ドキュメントを含むコン テナ • コレクション内でユニー クなドキュメントIDで管 理される { "name": "Nobita", "skill": "Hirune" } nvGvwR5 { "name": "Suneo", "skill": "Jiman" } zzD7UAv users

Slide 9

Slide 9 text

サブコレクション { "name": "general" } CSP36ah { "name": "random" } CSP4CQz channels messages { "from": "AAd7UZv", "message": "何してますか?忙しいですか..." } MV5ahcO { "from": "nvGvwR5", "message": "昼寝してた" } MV5yaC0 { "from": "AAd7UZv", "message": "近くのコンビニエンスストアで..." } MV6Almn { "from": "nvGvwR5", "message": "まかせといてよ" } MV6L38V messages ...

Slide 10

Slide 10 text

データのリアルタイム取得 Firestore.firestore() .collection("users") .addSnapshotListener{ snapshot, error in // snapshot?.documents[0].documentID ... String // snapshot?.documents[0].data() ... [String: Any] } コレクション

Slide 11

Slide 11 text

データのリアルタイム取得 Firestore.firestore() .collection("channels").document("CSP36ah") .collection("messages") .addSnapshotListener{ snapshot, error in // snapshot?.documents[0].documentID ... String // snapshot?.documents[0].data() ... [String: Any] } サブコレクション

Slide 12

Slide 12 text

データのリアルタイム取得 Firestore.firestore() .collection("users") .whereField("age", isGreaterThan: "18") .order(by: "age") .order(by: "name") .addSnapshotListener{ snapshot, error in // snapshot?.documents[0].documentID ... String // snapshot?.documents[0].data() ... [String: Any] } クエリ

Slide 13

Slide 13 text

スタブりにくそう なので、 • すべての機能のスタブは作らない • 自分が必要なものだけ(なるべく妥協する) • Cloud Firestoreのインタフェースそのままでは やらない

Slide 14

Slide 14 text

どうやってスタブるか? Firestore App

Slide 15

Slide 15 text

DataStore どうやってスタブるか? Firestore App ある程度、操作を制限

Slide 16

Slide 16 text

どうやってスタブるか? DefaultDataStore Firestore StubDataStore App 通常時 テスト時 DataStore

Slide 17

Slide 17 text

コレクションの指定 protocol CollectionPath • コレクションを指す概念を抽象化 collection("channels") .document("CSP36ah") .collection("messages")

Slide 18

Slide 18 text

クエリ protocol DataStoreQuery • クエリを指定する概念を抽象化 • CollectionPathもDataStoreQuery(プロトコルを継承) collection("channels") .whereField("age", isGreaterThan: "18") .order(by: "age") .order(by: "name")

Slide 19

Slide 19 text

クエリ=フィルタ+ソート collection("channels") .whereField("age",
 isGreaterThan: "18") .order(by: "age") [Entity] .filter(...) .sorted(...) documentID: String data: [String: Any]

Slide 20

Slide 20 text

リアルタイムなデータ取得 DataStoreQueryにマッチするEntityの配列が
 リアルタイムに流れてくる

Slide 21

Slide 21 text

リアルタイムなデータ取得 DataStoreQueryにマッチするEntityの配列が
 リアルタイムに流れてくる RxSwiftのObservable func observeCollection(matches query: DataStoreQuery) -> Observable<[Entity]>

Slide 22

Slide 22 text

スタブるぞ • CollectionPathごとに Observableを保持しておく StubDataStore /channels /channels/CSP36ah/messages Observable<[Entity]> Observable<[Entity]>

Slide 23

Slide 23 text

/channels /channels/CSP36ah/messages Observable<[Entity]> Observable<[Entity]> スタブるぞ • DataStoreQueryに応じて、 フィルタ、ソートを行う Observableをmapで変換し て返す StubDataStore filter(...) sorted(...) Observable<[Entity]> func observeCollection(matches query: DataStoreQuery) -> Observable<[Entity]> map

Slide 24

Slide 24 text

/channels /channels/CSP36ah/messages Observable<[Entity]> Observable<[Entity]> filter(...) sorted(...) Observable<[Entity]> map スタブるぞ • 元のObservableに更新が 流れれば、さっき返した Observableにも自動的に (リアルタイムに)更新 が流れる StubDataStore ✨ ✨

Slide 25

Slide 25 text

更新系メソッドも まるっとやれば

Slide 26

Slide 26 text

ほら、スタブれた ⭐ https://github.com/hironytic/CloudFirstoreStubPOC

Slide 27

Slide 27 text

まとめ • Cloud Firestoreのスタブを作った(スタブった) • 必要な操作にしぼってスタブりやすくした • RxSwiftのおかげでリアルタイムなデータ取得の部 分がうまいこといった • 作ったとは言ったが、使いものになるとは言って いない