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

Zenject Testing LT

Nozomi Tanaka
September 06, 2018

Zenject Testing LT

Nozomi Tanaka

September 06, 2018
Tweet

More Decks by Nozomi Tanaka

Other Decks in Technology

Transcript

  1. Zenjectの機能をご紹介
    〜テストの巻〜
    2018/09/06
    Nozomi Tanaka @nozomin770

    View Slide

  2. 自己紹介
    ● 名前 Tanaka Nozomi
    ○ メインクラス:Unityつかい
    ○ サブクラス:Ruby on Railsつかい
    ○ ソシャゲをつくるおしごとをしています
    ● Twitter : https://twitter.com/nozomin770
    ● キックボードに乗ることにハマった
    テストコードの書き方極めるのにハマってます

    View Slide

  3. 想定する読者
    ● すでにテストを完全に理解した方
    ● さらにZenjectをそれとなく理解した方
    ● Zenject無しでテストは書けるぜ! って方
    ● ここまでの発表を完全に理解してZenjectを使いこなせる方
    ● さらなる自動テストを目指す方

    View Slide

  4. えっ・・・

    View Slide

  5. もくじ的なもの
    ● ZenjectがサポートしているUnityのテスト手法
    ● ZenjectUnitTestFixtureとは
    ● ZenjectIntegrationTestFixtureとは
    ● SceneTestFixtureとは
    ● 幻の第四のテスト
    ● まとめ

    View Slide

  6. Zenjectでテスト…とな?

    View Slide

  7. そもそもZenjectでテストって一体
    ● ZenjectがUnityTestToolsにサポートを入れてくれている、ということ。
    ● EditModeTestはもちろん、PlayModeTestにもサポートが入っている
    ● さらに、SceneTestという、Zenjectの権能を使うTestを書くことができる
    ● Zenjectを組み込んだプロジェクトは、テストコードでも
    Zenjectの意思に従うことができるのだ・・・

    View Slide

  8. ZenjectUnitTestFixtureという力

    View Slide

  9. ZenjectUnitTestFixture
    ● Zenjectが用意してくれているクラス
    ● 中身は非常にシンプル、継承して使う

    View Slide

  10. ZenjectUnitTestFixture
    ● このクラスを使うとできること
    ○ UnityTestToolsのEditModeTestを記述するときに、Zenjectの機能を使える
    ● 具体的には…
    ○ [SetUp]時にテストしたいクラスを Bindしておき
    ○ [Test]を書いたテストケースごとに Resolveでインスタンスを取得できる
    ● さらに…
    ○ SetUpで事前にInjectしておくことで、各テストケースでインスタンス準備を省ける

    View Slide

  11. ZenjectUnitTestFixture
    ● これらを活用することで出来ること
    ○ EditModeTestに対応できるC#のPureClassをテストするとき、DIを行うことができる
    ○ テストに使うモッククラスを事前に Bindしておくことで、Zenjectが依存性を解決
    ○ モックオブジェクトを用意して Resolveで食わせる設定をすることも可能
    ● 単体クラスのテストでは強みは薄いが、こういったケースでは強い
    ○ 複数のマスターデータを使う、ビジネスロジックのテスト
    ■ マスターデータはZenjectが全てDIしてくれるので、テストコード量が減る
    ■ 工夫すれば都度Resolveでもらうモックの内容を差し替えることも可能 …

    View Slide

  12. ZenjectIntegrationTextFixtureという力

    View Slide

  13. ZenjectIntegrationTestFixture
    ● このクラスを使うとできること
    ○ PlayModeTestを実行するときにZenjectの権能を使うことができる
    ● 具体的には…
    ○ このクラスを継承すると、 [UnityTest]を実行するときにZenjectの権能が発揮される
    ○ テスト実行時に3箇所のタイミングでZenjectの処理などを挟むことができる
    ○ PlayModeTestなので、ContextやInstallerなどはすべて動作してくれる
    ● ようするに、PlayModeTestでZenject使えるマン

    View Slide

  14. ZenjectIntegrationTestFixture
    ● これらを活用することで出来ること
    ○ PlayModeTestでZenjectが動く!(語彙消失)
    ○ PreInstallというメソッドを呼ぶ前に、 PlayModeで使うシーンを指定したり、シーンに操作が加えら
    れる
    ○ PostInstallというメソッドを呼ぶ前に、テストに必要なバインド処理を記述できる
    つづく

    View Slide

  15. ZenjectIntegrationTestFixture
    ● これらを活用することで出来ること 2
    ○ PostInstallメソッドを呼んだ後、 Zenjectの処理がすべて起動する
    ○ IInitializable.Initializeも呼ばれる
    ○ このあとにテストが記述できる
    ○ この瞬間はMonoVehaviour.Awakeのタイミングなので、 Startも呼ぶには一度yieldしておくこと
    つづく

    View Slide

  16. ZenjectIntegrationTestFixture
    ● つまりどういうことだってばよ
    ○ 基本的なPlayModeTestの実行時に、Zenjectの全機能が起動可能
    ○ PostInstall前にバインド処理を自分で記述することで、 PlayModeTestでモックを参照させることも
    できる
    ● ところがどっこい、SceneTestのが強いので、こっちを使うのは稀かも?

    View Slide

  17. SceneTestFixture…?

    View Slide

  18. SceneTestFixtureという深淵
    ● こやつはいったい
    ○ これを継承したクラスでも、 PlayModeTest時にZenjectの権能が使える
    ○ Zenjectの神の力「StaticContext」を使うことで、Testするときに自在なパラメータを注入してしまう
    ことができる
    ● やばい

    View Slide

  19. SceneTestFixtureヤバイ
    ● やれることのベースはIntegrationTestと同じだが、思想が違う
    ● テストのSetUpから権能を発揮しているので、自在にContextに操作が加えられる
    ● StaticContextが所有するコンテナにBindを行うと、SceneContextが持つ
    InstallerでBindしたインスタンスを上書きしてBindされます
    ● これを使うと・・・

    View Slide

  20. SceneTestFixtureヤバイ
    ● Zenjectで構築されたインゲームに対してデータ注入したテストができる
    ○ 例:シューティングゲームで敵の速さを数段階設定、意図した結果になったかテスト
    ○ 例の例:敵が弱い設定を注入したとき、プレイヤーは勝利する
    ○ 例の例:敵が強い設定を注入したとき、プレイヤーは敗北する
    ● 実データを投入したテストで、例外が出ないか検知するテストができる
    ○ PlayModeTestを完全に使いこなすことで、自動テストを構築したのち
    ○ 実データを投入、それを実行したときにエラーが出ないかテストできる
    ○ 毎日回すとエラーが出たときにすぐ分かる!

    View Slide

  21. Zenjectこそ神の意志

    View Slide

  22. SceneTestFixtureヤバイ
    ● 自動テストを構築しましょう
    ○ まずはそこから。SceneTestFixtureを使ったテストを作成
    ○ 運用データを投入、たとえばゲームのホーム画面が出るまで、エラーが出ないことをテスト
    ● Zenjectの権能で検証データを注入しましょう
    ○ StaticContextの権能を使えば、あらゆる Containerに干渉できます
    ○ 思いっきり検証用のデータを作りまくりましょう
    ○ なんならマスターデータから自動でテストコードを作りましょう(真顔)
    ● すると不思議、オートテストができる!!!

    View Slide

  23. ちょっとまてや
    ● 入力はどうすんだよ???
    ○ 悩みどころですね。Zenjectができるのはあくまで DIまで。
    ○ Zenjectが注入するオブジェクトはテストで自在に変えられますが、結局それまで。
    ○ テスト完全に理解した人たちなら、 PlayModeTestで入力をyieldで待つくらい出来るよ!

    View Slide

  24. とはいえ凄い
    ● テストコードを真面目に書くと感じると思うこと
    ○ テストデータの用意がめんどう
    ○ テストデータの依存解決も面倒
    ■ これはテストに限らないので、 Zenjectを使うわけですね
    ○ Zenjectを使うとテストですら依存解決を Zenjectがしてくれる
    ○ しかも、用意するテストデータは Bind時に個別につくればよい
    ■ いっそテストケースごとに使うデータを全部 BindしてID指定もあり
    ■ もちろんテストケースごとに Bind処理を書くのもあり
    ■ データを用意することに注力できるのは、テスト工数の削減につながるねん

    View Slide

  25. 幻の第四のテスト

    View Slide

  26. View Slide

  27. 完全に理解した
    (わかってない)

    View Slide

  28. User Driven Test Bedsって…
    ● 手で動かしてねということ
    ● 立派なテストです(と公式が言ってる)
    ● 自動でできないのが難点・・・
    ● 見なかったことにしましょう

    View Slide

  29. うまい感じに使うまとめ

    View Slide

  30. まとめ
    ● EditModeTestでZenjectを使いたいなら、UnitTestFixtureを使おう
    ○ UnitTestと言ってるけどEditModeでIntegrationTestする場合も使える
    ● PlayModeTestでは、まずはIntegrationTestFixtureを使おう
    ○ 動作に慣れましょう。基本的には Play時と同じですが、PlayModeTestの書き方に慣れよう
    ● 自動でPlayModeTestを流したくなったそこのあなた、SceneTestを使おう
    ○ 自動テスト環境の構築からはじめるんですけどね!!!
    ○ 一度作ればユートピア、データを注入し放題〜〜〜

    View Slide

  31. 自動テスト環境を作れるほど
    テスト理解してたら
    苦労しないよ・・・

    View Slide

  32. 〜FIN〜

    View Slide