Upgrade to Pro — share decks privately, control downloads, hide ads and more …

自動テストでモックするって、なにそれ?おいしいの?/what_is_mocking

marchin
April 14, 2022

 自動テストでモックするって、なにそれ?おいしいの?/what_is_mocking

marchin

April 14, 2022
Tweet

More Decks by marchin

Other Decks in Programming

Transcript

  1. 自動テストでモックするって、
    なにそれ?おいしいの?
    〜依存コンポーネントをコントロールして、上手なテストコードを実装しよう〜

    View Slide

  2. 自己紹介
    - 名前: 阿部 真之
    - 仕事: 株式会社ゆめみ でAndroidエンジニアしてます
    - 最近はサーバサイド Kotlinの仕事も始めました
    - 趣味
    - コーヒー、ビール、アニメ、ゲーム、読書、 etc…
    - Twitter: @marchin_1989

    View Slide

  3. アジェンダ
    - ユニットテストの例
    - テストダブルとは
    - テストダブルの分類(サンプルコードで解説)
    - その他注意点など

    View Slide

  4. ユニットテスト書いてますか?

    View Slide

  5. ユニットテスト
    コンピュータプログラミングにおいて単体テスト(たんたいテスト)あるいはユニットテスト
    (英語: Unit test)とは、ソースコードの個々のユニット、すなわち、1つ以上のコンピュー
    タプログラムモジュールが使用に適しているかどうかを決定するために、関連する制御
    データ、使用手順、操作手順とともにテストする手法である。ユニットとはアプリケーショ
    ンのテスト可能な最小の部品単位である、と直観的にとらえることができる。
    (Wikipedia)
    ここでは、自動テストの文脈でユニットテストをみていきます。

    View Slide

  6. ユニットテストしてみよう

    View Slide

  7. - テストダブルってなに?
    - モック、スパイ、ダミーとか聞いたことあるけど。。
    テストダブル?

    View Slide

  8. テストダブルとは?
    - テストダブルとは、テスト実行時に、テスト対象が依存している外部のコンポーネン
    トと置き換わるもの。
    @Test
    fun `テストコード`() {
    assertEquals(期待値, テスト対象())
    }
    fun テスト対象(): Int {

    依存コンポーネントのメソッド()

    }

    View Slide

  9. 本番
    テスト

    View Slide

  10. なぜテストダブルに置き換えたいのか
    テスト対象が外部のコンポーネントに依存しており、テスト環境で利用できなかったり、
    利用しづらかったりなど、制約(コスト、処理時間)があるとき。
    - テストに必要な結果をコントロールできない(実行するたびに値が変わる)
    - 実行に時間がかかる
    - 用意するのにお金がかかる

    View Slide

  11. テストダブルにはどんなものがあるの?
    - xUnit Test Patternsによる定義、分類が有名
    - xUnit Test Patternsとは、テスト自動化フレームワークの xUnit(JUnitやNUnitなど)を使用して自動
    テストを作成するためのパターン (本)。
    - 分類
    - ダミー(Dummy Object)
    - スタブ(Test Stub)
    - スパイ(Test Spy)
    - モック(Mock Object)
    - フェイク(Fake Object)
    出典: xUnit Test Patterns Test Double
    http://xunitpatterns.com/Test%20Double.html

    View Slide

  12. テストダブルの分類を知っておく利点
    - それぞれの役割を理解しておくと、テストダブルに対して何をやらせばいいのか明
    確になる。適切なテストダブルを選べる。
    - モックライブラリのAPIが何を提供しているのか理解しやすくなる。
    - ただし、xUnit Test Patternsのテストダブルの分類と言葉が一致しなかったりするので要注意。
    - (逆説的だが)自分が作成したいテストケースが明確になる。

    View Slide

  13. 以降の説明の流れ
    - テストダブルとその分類
    - それぞれ、実際にどうやって置き換えるのか、サンプルコードで紹介(Kotlin)

    View Slide

  14. テストダブルの分類

    View Slide

  15. 外部からの入力 外部への出力 主な役割
    ダミー × × 何もしない。インスタンスが必要になる場合に利用。
    スタブ ◯ × 外部コンポーネントからの入力を操作する
    スパイ ◯ ◎ 外部コンポーネントへの出力を記録する
    出力結果をテストコードから取り出して評価
    モック ◯ ◎ 外部コンポーネントへの出力を記録する
    出力の期待結果を持ち、モック内で評価
    フェイク ◯ ◯ 本物ではないが、本物と同じように動作する
    テストダブルの分類

    View Slide

  16. 外部からの入力 外部への出力 主な役割
    ダミー × × 何もしない。インスタンスが必要になる場合に利用。
    スタブ ◯ × 外部コンポーネントからの入力を操作する
    スパイ ◯ ◎ 外部コンポーネントへの出力を記録する
    出力結果をテストコードから取り出して評価
    モック ◯ ◎ 外部コンポーネントへの出力を記録する
    出力の期待結果を持ち、モック内で評価
    フェイク ◯ ◯ 本物ではないが、本物と同じように動作する
    テストダブルの分類
    主に「外部への入出力」でテ
    ストダブルを分類

    View Slide

  17. 外部からの入力 外部への出力 主な役割
    ダミー × × 何もしない。インスタンスが必要になる場合に利用。
    スタブ ◯ × 外部コンポーネントからの入力を操作する
    スパイ ◯ ◎ 外部コンポーネントへの出力を記録する
    出力結果をテストコードから取り出して評価
    モック ◯ ◎ 外部コンポーネントへの出力を記録する
    出力の期待結果を持ち、モック内で評価
    フェイク ◯ ◯ 本物ではないが、本物と同じように動作する
    テスト対象への入力
    のコントロール
    テストダブルの分類

    View Slide

  18. 外部からの入力 外部への出力 主な役割
    ダミー × × 何もしない。インスタンスが必要になる場合に利用。
    スタブ ◯ × 外部コンポーネントからの入力を操作する
    スパイ ◯ ◎ 外部コンポーネントへの出力を記録する
    出力結果をテストコードから取り出して評価
    モック ◯ ◎ 外部コンポーネントへの出力を記録する
    出力の期待結果を持ち、モック内で評価
    フェイク ◯ ◯ 本物ではないが、本物と同じように動作する
    テスト対象からの出
    力の記録
    テストダブルの分類

    View Slide

  19. ダミー

    View Slide

  20. ダミー(Dummy Object)
    - テストメソッド内で、なにもしない。
    - テスト対象に影響を与えないが、コンパイルなどの都合上、用意しないといけないも
    の。

    View Slide

  21. ダミーのサンプルコード

    View Slide

  22. スタブ

    View Slide

  23. スタブ(Test Stub)
    - 入力を操作し、任意の値をテスト対象に与える。
    - 入力値をテストコード上で、事前設定し、テストを実行。

    View Slide

  24. スタブのサンプルコード

    View Slide

  25. スパイ

    View Slide

  26. スパイ(Test Spy)
    - テスト対象からの出力を記録。
    - テストコード上でその記録した出力を検証する。
    - ただし、入力を操作することもある。つまりスタブのように振る舞うこともある。

    View Slide

  27. スパイのサンプルコード

    View Slide

  28. モック

    View Slide

  29. モック(Mock Object)
    - テスト対象からの出力を記録
    - テスト対象内の外部コンポーネントへの出力の期待結果(expected)をセットする
    - テスト対象を実行しながら、テスト対象から外部コンポーネントへの出力を取得し、
    モック内部で期待結果と出力結果を比較して、成功か失敗かを判定する
    - テストコードからは、モックから検証の成功 or 失敗を受け取る
    - スタブの機能を持つことがある

    View Slide

  30. スパイとモックの違い
    - 両方とも、外部コンポーネントへの出力を検証するためのテストダブル。
    - ただし、モックは、テスト対象のメソッドを呼び出す前に、事前に期待結果をセットす
    る。その後、モック内で出力の結果を評価する。
    - スパイは、外部コンポーネントへの出力を保持するだけ。外部コンポーネントへの
    出力結果の評価は後からテストコード上で行う。

    View Slide

  31. フェイク

    View Slide

  32. フェイク(Fake Object)
    - テスト実行中、本物ではないが、本物と同じように動作する。
    - 本物がテスト環境で使えないとか、返答が遅いなどの理由で利用する。
    - テストの実行環境のマシンで起動しておいて、接続先を変更するなどで置き換える
    - 例
    - RDBに対し、同じ機能を持ったオンメモリのデータベース。
    - AWSの機能をエミュレートした LocalStack。DynamoDB Local。

    View Slide

  33. 以上、テストダブルの分類でした

    View Slide

  34. その他
    - ややこしいが、テストダブルの生成を単に「モックする」ということがある。

    View Slide

  35. その他
    - ややこしいが、テストダブルの生成を単に「モックする」ということがある。
    - 「スタブの入力値自体をテストする」のような意味のないユニットテストを書いてしま
    うことがあるので注意。

    View Slide

  36. その他
    - ややこしいが、テストダブルの生成を単に「モックする」ということがある。
    - 「スタブの入力値自体をテストする」のような意味のないユニットテストを書いてしま
    うことがあるので注意。
    - テストダブルは、まだ実装していないコードの代替となる。

    View Slide

  37. その他
    - ややこしいが、テストダブルの生成を単に「モックする」ということがある。
    - 「スタブの入力値自体をテストする」のような意味のないユニットテストを書いてしま
    うことがあるので注意。
    - テストダブルは、まだ実装していないコードの代替となる。
    - モックライブラリで実装されている名前と、xUnit Test Patternsのテストダブルの分
    類は必ずしも一致しない

    View Slide

  38. その他
    - ややこしいが、テストダブルの生成を単に「モックする」ということがある。
    - 「スタブの入力値自体をテストする」のような意味のないユニットテストを書いてしま
    うことがあるので注意。
    - テストダブルは、まだ実装していないコードの代替となる。
    - モックライブラリで実装されている名前と、xUnit Test Patternsのテストダブルの分
    類は必ずしも一致しない
    - モックライブラリによっては挙動が異なるので、利用するときはよく挙動を理解して
    おくこと
    - rspec-mocks(Ruby)のスパイは、置き換えられた本物の依存コンポーネントの処理は実行されな

    - MockK(Kotlin)やJest(JavaScript)のスパイは、デフォルトだと、置き換えられた依存コンポーネン
    トの処理も実行される。プロキシのような挙動。

    View Slide

  39. 外部からの入力 外部への出力 主な役割
    ダミー × × 何もしない。インスタンスが必要になる場合に利用。
    スタブ ◯ × 外部コンポーネントからの入力を操作する
    スパイ ◯ ◎ 外部コンポーネントへの出力を記録する
    出力結果をテストコードから取り出して評価
    モック ◯ ◎ 外部コンポーネントへの出力を記録する
    出力の期待結果を持ち、モック内で評価
    フェイク ◯ ◯ 本物ではないが、本物と同じように動作する
    まとめ
    テスト対象への入力
    のコントロール
    テスト対象からの出
    力の記録

    View Slide