How To Remodel Current Testing Environment

How To Remodel Current Testing Environment

Day1, DroidKaigi 2017

D4133d8efb46ae872d7a563b619bfc83?s=128

Matsuda Jumpei

March 09, 2017
Tweet

Transcript

  1. How To Remodel Current Testing Environment Day1, DroidKaigi 2017

  2. はじめに 本発表はIEEE829やウ ン タ ラ 29119には準拠してい ません (喧嘩を売るつもりもありません)

  3. About me Jumpei Matsuda Working at Quipper Limited twitter/@red_fat_daruma, github/jmatsu

  4. 既存のテストの価値・役割を理解してま すか?

  5. テストの価値・役割 精神的保険? テストありきの開発? 仕様と同等?

  6. テストを精神的保険とする開発 テストは精神的安定のために存在している アプリの動作保証 < 精神的安定 失敗すると「直すのが面倒くさい」が先行する 最悪、あとで直せばいい テスト = 自己満足

  7. テストありきの開発 Test Driven Development 段階受け入れテストを用いた開発

  8. Test Driven Development テストの作成・実行を開発サイクルに組み込む 1. ユニットテストを書く (実行すると fail する) 2.

    ざくっと実装する 3. ユニットテストが通る 4. 合意を得られるまでリファクタリングする 5. 1~4を繰り返す テスト = 開発プロセスを構築するファクター
  9. 段階受け入れテストを用いた開発 各段階テストの受け入れがリリースの条件 JUnit test Android Instrumentation test UI test, happy

    path test, scenario test テスト = Quality Assurance
  10. 仕様と同等なテストを用いた開発 Behavior Driven Development 基本的にDSLを用いて記述 フレームワークの制約がつく Given, When, Then 初期コンテキスト,

    契機イベント, 結果の保証 テスト = 仕様
  11. 既存のテストの価値・役割を説明でき る?

  12. Room3 @Nkznさんによる React Nativeの話が面白いと思います

  13. How To Remodel Current Testing Environment

  14. Model/‑ing と Re‑model‑ing

  15. Model 抽象化により知り得た側面や性質を持つ構造・ 外観 Model‑ing 特定の側面や性質を持つ構造・外観を作ること

  16. Remodel‑ing 既存モデルの変更により、目的のモデ ルを得ること リファクタリングではない

  17. Remodelingにより得たい恩恵 テストの信頼度向上 テスト負債の返上 テストの安定化 欠落したテストの補完 不必要なテストの削除

  18. Remodelingのステップ 1. 現存するテストの理解・掌握 2. 目的モデルの選定 3. 目的モデルの構築

  19. Remodelingのステップ 1. 現存するテストの理解・掌握 2. 目的モデルの選定 3. 目的モデルの構築

  20. 現存するテストの理解 e.g. タイムアウトを利用した検証 I T o k e n R

    e p o s i t o r y t o k e n R e p o s i t o r y = m o c k ( ) ; I A u t h U s e C a s e u c = n e w A u t h U s e C a s e ( t o k e n R e p o s i t o r y ) ; u c . r e q u e s t L o g I n ( u s e r I d , p a s s w o r d ) ; / / a s y n c e x e c u t i o n T h r e a d . s l e e p ( 3 0 0 0 ) ; M o c k i t o . v e r i f y ( t o k e n R e p o s i t o r y ) . c r e a t e ( a n y ( ) ) ;
  21. 現存するテストの理解 e.g. タイムアウトを利用した検証 I T o k e n R

    e p o s i t o r y t o k e n R e p o s i t o r y = m o c k ( ) ; I A u t h U s e C a s e u c = n e w A u t h U s e C a s e ( t o k e n R e p o s i t o r y ) ; u c . r e q u e s t L o g I n ( u s e r I d , p a s s w o r d ) ; / / a s y n c e x e c u t i o n T h r e a d . s l e e p ( 3 0 0 0 ) ; v e r i f y ( t o k e n R e p o s i t o r y ) . c r e a t e ( a n y ( ) ) ; 3000ms という値に意味はある?
  22. 現存するテストの理解 e.g. タイムアウトを利用した検証 非機能要件との関係を疑う 3000ms 以内にレスポンスを返すべきという要件 テストコードとして 3000ms には意味がある 非機能要件にない

    C o u n t D o w n L a t c h や F u t u r e # a w a i t の方が適切
  23. Modelingの要素例 運用的側面 テストポリシー・ストラテジー 要件保証 手動 or 自動 技術的側面 言語・フレームワーク・実行環境 分類・頻度

    Mock‑able and/or Inject‑able
  24. 運用的側面 テストポリシー・ストラテジー 要件保証 手動 or 自動

  25. テストポリシー 組織の視点から見た「原則・目的」 PMやEXEの理解が必要 テストストラテジー テスターなどのステークホルダーに必要な側面 テスト環境等 ポリシーに基づいた上で、テストレベル別に用 意

  26. 考えたくないくらい定義が重いので この定義は使いません

  27. テストポリシー プロジェクトにおけるテストの意味・役割 テストストラテジー ポリシーを基にした、テスト作成・実行に必要 な要件 受け入れ基準や手法、テスト環境など テストケースの仕様ではない テストレベルごとに存在

  28. テストポリシー・ストラテジー テストの意味・役割・手法の理解を支援 どの要件を満たすためのテストか 開発者間での認識の共通化を支援 どのようなテストを書くべきか テストポリシー・ストラテジーが用意できない ⇒ 開発者それぞれでテストに対する価値認識が異なる可 能性

  29. 運用的側面 テストポリシー・ストラテジー 要件保証 手動 or 自動

  30. 要件保証 ‑ とある教育系アプリ 生徒用・教師用(保護者用)のサービスが共存 e.g.) ビジネス要件 2サービス間に成績表示の差異がない 課題の正答率がプラットフォームに依存しない オフラインでも動作して欲しい ビジネスロジック・永続化ロジックを保証した

  31. 運用的側面 テストポリシー・ストラテジー 要件保証 手動 or 自動

  32. 手動 or 自動 ⇒ 労働コストと金銭コストのせめぎ合い 手動 人の命を削れば実現できる ヒューマンエラーの入る余地がある 自動 実行環境自体に金がかかる

    自動テストコードの技術的ハードル
  33. 技術的側面 言語・フレームワーク・実行環境 サイズ・頻度 Mock‑able and/or Inject‑able

  34. 利用言語・フレームワーク Java, Kotlin, Groovy? JUnit, Spek, Spock? Robolectric, mockable‑jar?

  35. 実行環境 実機・エミュレータ リソース的に自由に利用できる環境が必要 Robolectric (Robospock) マシンのJDKとShadowでエミュレートする Java SL実装やNative Libraryが違う

  36. 技術的側面 言語・フレームワーク・実行環境 分類・頻度 Mock‑able and/or Inject‑able

  37. 分類の例 : Test Size https://testing.googleblog.com/2010/12/test‑sizes.html Feature Small Medium Large Network

    access No localhost only Yes Database No Yes Yes File system access No Yes Yes Use external systems No Discouraged Yes Multiple threads No Yes Yes Sleep statements No Yes Yes System properties No Yes Yes Time limit (seconds) 60 300 900+
  38. 分類の例 : テストの段階 Unit test Android Instrumentation test UI test

    happy path test scenario test
  39. 技術的側面 言語・フレームワーク・実行環境 分類・頻度 Mock‑able and/or Inject‑able

  40. Mock‑able or Inject‑able Mockable Test Doubleの思想が導入できる Injectable テスト用のクラスに置換できる

  41. Test Double 名称 用途 Dummy ただの引数埋めオブジェクト Fake 本番には不適な一時実装 Stub 静的な値を返す実装

    Spy 呼び出し情報を記録する実装 Mock 期待動作の登録と検証が可能
  42. Test Doubleの思想が導入できる ⇒ Doubleの取捨選択が可能 ストラテジーやオブジェクトの用途に依存 e.g. WhiteBox or BlackBox 某有名ライブラリであるMockitoは?

    MockとSpyの利用が多い 上記2つの"使い分け" がテストコードに意味を持た せる
  43. Injectable テスト用のクラスに置換できる DIツールを利用していることとは違う ぬくもり溢れるconstructor injection ぬくもり溢れるSetter

  44. Remodelingのステップ 1. 現存するテストの理解・掌握 2. 目的モデルの選定 3. 目的モデルの構築

  45. e.g. とある教育系アプリのモデリング 運用的側面 DB操作・プレゼンテーション前の変換層をテスト ビジネス要件の保証が最重要 分類は特になし 普段はCIでテストを回す リリース時は手動のhappy path

  46. e.g. とある教育系アプリのモデリング 技術的側面 Unit test (on all branch) Groovy +

    Robospock Instrumentation test (on master/release) Java + Emulator Mockableだけど、Injectableとは言えない Constructor Injectionはあまりない 初期化時に処理が発生し、Setterでは対応不可
  47. Remodelingのステップ 1. 現存するテストの理解・掌握 2. 目的モデルの選定 3. 目的モデルの構築

  48. とある教育系アプリ (再掲) 生徒用・教師用(保護者用)のサービスが共存 ビジネス要件の例 2サービス間に成績表示の差異がない 課題の正答率がプラットフォームに依存しない オフラインでも動作して欲しい ビジネスロジック・永続化ロジックを保証した い

  49. ビジネスロジック・永続化ロジックの保 証 ⇒ Given, When, Thenが明確 ⇒ BDDがうまくハマる

  50. ビジネスロジック・永続化ロジックの保 証 ⇒ Given, When, Thenが明確 ⇒ BDDがうまくハマる ≠ BDDを導入できる

  51. BDDの導入実現性 Mockable and Injectable を満たすべき 満たしていないなら・・・? リファクタリングする 他の手法にする

  52. とある教育系アプリでは・・・ Constructor Injectionへ変更 Dagger2を一部で利用 基本的にWhiteBoxテスト 細かい分岐は「開発者が知るべき知識なため」 Robospockは利用継続 UIテストの追加 ログイン・登録周りの保証のため 金で殴れば解決する事項は金で解決

  53. とある教育系アプリでは・・・(今後) DIツールの適用箇所増加 Robolectricの排除 OpenSTFを使う(現在移行作業中) マルチモジュール化 ビジネスロジック+テストの抽出 テストフレームワークを切り替えられる お金を稼いでさらに金で解決する

  54. まとめ テストの価値・役割を理解する 既存環境のモデリング 運用的側面と技術的側面を捉える 目的モデルを選定する 保証すべき要件からボトムアップで作成 目的モデルの構築 必要なら先にリファクタリングをする