読者です 読者をやめる 読者になる 読者になる

try! Swift Swiftにおける実践的なモック化について #tryswiftconf Day3-3

try! Swift 2016

Veronica Ray

LinkedInのビデオチームに所属するソフトウェアエンジニアです。以前自転車でヘラジカの間を通り抜けたことがあります。MediumのブログとTwitterでは@nerdonicaとして活動しています。

twitter.com

モックを使うと、プロダクションのデータが揃うのを待たずに、早くテストを書くことができます。OCMockを使わずにモックを書く場合でも、それほど多くの作業が発生するわけではありません。講演では、コードベースの多くの重要な箇所に対して簡単でメンテナンスしやすい実践的なモックを作るためのテクニックをSwiftで説明します。

f:id:niwatako:20160304112730j:plain

テストを書いてシステムを壊したり

f:id:niwatako:20160304112905j:plain

遅すぎてもこまる

f:id:niwatako:20160304112923j:plain

非同期テストはしにくい、遅くなる

f:id:niwatako:20160304112937j:plain

OCMockがあるがかなり制限がある

f:id:niwatako:20160304112956j:plain

Mockingフレームワークはリフレクションの上に成り立っている。Swiftはリードオンリーで実行中の者を変更できない。これがSwiftを安全にしていますが。

Swiftでは自分で仕組みを作る

f:id:niwatako:20160304113100j:plain f:id:niwatako:20160304113106j:plain

厳正な事実が有ります。

これをするには時間がかかる!

f:id:niwatako:20160304113135j:plain

時間がかからない方法を紹介します。

f:id:niwatako:20160304113152j:plain

そもそもやる価値が有るのか?本物の型を作る意味があるのか、メンテする価値が有るのか、トレードオフを考えてモックを構築すべき

モックを作る3つの理由

f:id:niwatako:20160304130336j:plain

ネットワークがあると遅くなるので、モックを作れば早くなる。

カバレッジを上げる、エラーや例外はシミュレーションしないとテストできない。危険なソースや何かファイルを削除するとかDBを消すとかはテストでないと難しい

システムそのものが影響を受けてテストが失敗する、副作用を及ぼす、設定ファイルを書き換えてしまう恐れなど

テストを追加するのはコードベースを改善する最高の方法です。

新たにリアクティブココアを使うとかコンカレンシーを改善するとかするなら、テストを書いて壊れないようにする。テストは実行可能なドキュメンテーションである。

やるべき時は、今でしょう。

テストは最初に書いたプログラマの頭のなかに存在するうちは簡単に出来ます。何年も立って解析するより。

だからチームでテストを各文化を作るべき。

DI

f:id:niwatako:20160304113539j:plain

デフォルトコンストラクタは引数なしに依存性を注入できる。しかし、DIコンテナを使う時にかなり問題が発生する。

タイフーンなどのフレームワークを使う時に問題が発生します。

f:id:niwatako:20160304113639j:plain

シングルトンでいい?

f:id:niwatako:20160304113649j:plain

DIを使う3つの理由

f:id:niwatako:20160304130453j:plain

  • 部分的なカスタマイズが簡単
  • オーナーシップが明確に
  • テスタビリティ隠された仕様がなくなる

Cunstructor Injection

f:id:niwatako:20160304113817j:plain f:id:niwatako:20160304113814j:plain

OCMock

f:id:niwatako:20160304113832j:plain

iOSでもJavaでも一貫した形になっている。

Stub

f:id:niwatako:20160304113855j:plain

レスポンスをなりすます、入れ替える。

最も一般的、レスポンスを代わりに出す

f:id:niwatako:20160304113912j:plain

Mock もう少し複雑になる

f:id:niwatako:20160304114009j:plain

メソッドやパラメータががセットされたかチェック f:id:niwatako:20160304114032j:plain

部分的モック 

f:id:niwatako:20160304114056j:plain

特定メソッドだけモックレスポンスを返す

f:id:niwatako:20160304114104j:plain

これはアンチパタン

f:id:niwatako:20160304114123j:plain

セットアップするだけでも大変。そして理解度、何が本物で何がモックかわからなくなる。

f:id:niwatako:20160304114146j:plain

ベストプラクティスが登場しています、Swiftのモッキングをプロトコルで行う。

f:id:niwatako:20160304114306j:plain

f:id:niwatako:20160304114312j:plain

f:id:niwatako:20160304114318j:plain 

f:id:niwatako:20160304114331j:plain

プロトコルのほうがサブクラスよりもたくさんのメリットがある。

f:id:niwatako:20160304114353j:plain

ストラクトとクラスとの相性が良い。一貫した形でモックを造れる。

依存性がある時にプロトコルを使うのが便利。

f:id:niwatako:20160304114416j:plain

プロトコルに準拠していればiOS変更に伴うタイプの変更などを気にしなくて済む。

f:id:niwatako:20160304114510j:plain

所有していないタイプのモックを辞めよ

同じようなこと言っている。

f:id:niwatako:20160304114525j:plain

よくない理由は2つ。

モックの振る舞いは外部ライブラリとマッチする必要がある。外部ライブラリを自分が理解する必要がある、そしてその実装は変わることがある。

f:id:niwatako:20160304114624j:plain

しかし必要になることもある。

f:id:niwatako:20160304114637j:plain

やるなら他に依存しない時

Appleのクラスをモックにするときはそのクラスとのインタラクションのみにすべきというアドバイスを頂きました。データにダメージを加える事を考えれば、良いと思います。

f:id:niwatako:20160304114749j:plain

私自身のプロジェクトではNotificationCenterのモックかは不要、数日必要レベル、Injection作業だけですごい大変、精度高いモックは大変だった、美しくないハックだらけに。Centerはモッキングで問題を避けることが出来る、リアルノーティフィケーション送らなくて良い、でも、私としてはCenterを使って問題を解決するのは良い方法ではない

f:id:niwatako:20160304114914j:plain

Valueタイプをモックしてはいけない

f:id:niwatako:20160304114922j:plain

シンプルなインアウトではモッキングは要らない

f:id:niwatako:20160304114937j:plain

モックを減らすならバリュータイプを減らせばいい

沢山コードベースがあるなら何処から始めたら良いでしょうか

f:id:niwatako:20160304115010j:plain

どうしたらリファクタリングで参照型を値がたにするか

f:id:niwatako:20160304115015j:plain

Imutableにしてほぼ同じ振る舞いにして共通トランジションポイントを作る。Immutableにして後でStructに変える。

f:id:niwatako:20160304130758j:plain

見直すと、何故クラスすなのか?と考えることが有りました。必要ないケースがあった。

モックを書いて分かったこと、優良なモックは、書くのが簡単。3日使っているなら時間投資の勝ちを見直しましょう

ひつようのない情報が沢山入っているなら避けましょう。所有しない型のモックは含めない。プロパティをデフォルトバリューに設定するときは必要な物だけを設定すべし。

かく、保守する、徹底したテストを書く、どちらが良いのか

タイムトラベラーの皆さん、将来を見ていきましょう。

Swiftモッキングフレームワークはどのようになるでしょう。

3つ出てきています。

f:id:niwatako:20160304130819j:plain

アプローチとしては独自のモックを書かなくてはいけないがHelper提供の形で期待値やリターンバリューを定義する。

f:id:niwatako:20160304115345j:plain

これはこれら3つと違ってサポートするクラス、ストラクトを作りOCMockに近い形でやる

f:id:niwatako:20160304115338j:plain

これは新しい世界に言っているのではないか?ファンクショナルコア、とか。インテリティブシェル?

こうしたものはおもちゃのようでまだ早いと思う。

昨日あやかさんの話で、アーキテクチャが初めて商用環境で使われているということにワクワクした

まとめ

f:id:niwatako:20160304115507j:plain

コードベースを改善したかったらモックテストを加工、シンプルなモックを書く

QA

昨日のセッションで目覚ましアプリなど有りましたが、日付や時間に依存すると清い方法は有りますか?

遭遇したことはないです。面白いトピックかもしれませんね。

気に入った記事は はてなブックマーク

はてなブックマークアプリiOS開発チームから来ました! はてなブックマークにはSwift特集があります! 良い記事を見逃さないように、ご利用ください! http://b.hatena.ne.jp/hotentry/it/Swift

そして良いまとめ記事があったらはてなブックマークでブックマークしましょう! try! Swift の記事で盛り上がると嬉しいです!