Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Zenject Testing LT
Search
Nozomi Tanaka
September 06, 2018
Technology
0
1.3k
Zenject Testing LT
Nozomi Tanaka
September 06, 2018
Tweet
Share
More Decks by Nozomi Tanaka
See All by Nozomi Tanaka
Gotanda.unity #10 メモリと闘う者達 〜GC編〜
barasixi
0
3.2k
Other Decks in Technology
See All in Technology
生成AIで小説を書くためにプロンプトの制約や原則について学ぶ / prompt-engineering-for-ai-fiction
nwiizo
3
830
GitHub Copilot の概要
tomokusaba
1
130
OpenHands🤲にContributeしてみた
kotauchisunsun
1
420
製造業からパッケージ製品まで、あらゆる領域をカバー!生成AIを利用したテストシナリオ生成 / 20250627 Suguru Ishii
shift_evolve
PRO
1
130
AIのAIによるAIのための出力評価と改善
chocoyama
2
540
Liquid Glass革新とSwiftUI/UIKit進化
fumiyasac0921
0
190
Snowflake Summit 2025 データエンジニアリング関連新機能紹介 / Snowflake Summit 2025 What's New about Data Engineering
tiltmax3
0
300
Observability в PHP без боли. Олег Мифле, тимлид Altenar
lamodatech
0
330
Model Mondays S2E02: Model Context Protocol
nitya
0
220
Oracle Cloud Infrastructure:2025年6月度サービス・アップデート
oracle4engineer
PRO
2
230
SalesforceArchitectGroupOsaka#20_CNX'25_Report
atomica7sei
0
140
初めてのAzure FunctionsをClaude Codeで作ってみた / My first Azure Functions using Claude Code
hideakiaoyagi
1
210
Featured
See All Featured
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.8k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
5
210
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Become a Pro
speakerdeck
PRO
28
5.4k
Optimizing for Happiness
mojombo
379
70k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
657
60k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
138
34k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
4 Signs Your Business is Dying
shpigford
184
22k
Building Adaptive Systems
keathley
43
2.6k
Typedesign – Prime Four
hannesfritz
42
2.7k
GitHub's CSS Performance
jonrohan
1031
460k
Transcript
Zenjectの機能をご紹介 〜テストの巻〜 2018/09/06 Nozomi Tanaka @nozomin770
自己紹介 • 名前 Tanaka Nozomi ◦ メインクラス:Unityつかい ◦ サブクラス:Ruby on Railsつかい
◦ ソシャゲをつくるおしごとをしています • Twitter : https://twitter.com/nozomin770 • キックボードに乗ることにハマった テストコードの書き方極めるのにハマってます
想定する読者 • すでにテストを完全に理解した方 • さらにZenjectをそれとなく理解した方 • Zenject無しでテストは書けるぜ! って方 • ここまでの発表を完全に理解してZenjectを使いこなせる方 •
さらなる自動テストを目指す方
えっ・・・
もくじ的なもの • ZenjectがサポートしているUnityのテスト手法 • ZenjectUnitTestFixtureとは • ZenjectIntegrationTestFixtureとは • SceneTestFixtureとは •
幻の第四のテスト • まとめ
Zenjectでテスト…とな?
そもそもZenjectでテストって一体 • ZenjectがUnityTestToolsにサポートを入れてくれている、ということ。 • EditModeTestはもちろん、PlayModeTestにもサポートが入っている • さらに、SceneTestという、Zenjectの権能を使うTestを書くことができる • Zenjectを組み込んだプロジェクトは、テストコードでも Zenjectの意思に従うことができるのだ・・・
ZenjectUnitTestFixtureという力
ZenjectUnitTestFixture • Zenjectが用意してくれているクラス • 中身は非常にシンプル、継承して使う
ZenjectUnitTestFixture • このクラスを使うとできること ◦ UnityTestToolsのEditModeTestを記述するときに、Zenjectの機能を使える • 具体的には… ◦ [SetUp]時にテストしたいクラスを Bindしておき
◦ [Test]を書いたテストケースごとに Resolveでインスタンスを取得できる • さらに… ◦ SetUpで事前にInjectしておくことで、各テストケースでインスタンス準備を省ける
ZenjectUnitTestFixture • これらを活用することで出来ること ◦ EditModeTestに対応できるC#のPureClassをテストするとき、DIを行うことができる ◦ テストに使うモッククラスを事前に Bindしておくことで、Zenjectが依存性を解決 ◦ モックオブジェクトを用意して
Resolveで食わせる設定をすることも可能 • 単体クラスのテストでは強みは薄いが、こういったケースでは強い ◦ 複数のマスターデータを使う、ビジネスロジックのテスト ▪ マスターデータはZenjectが全てDIしてくれるので、テストコード量が減る ▪ 工夫すれば都度Resolveでもらうモックの内容を差し替えることも可能 …
ZenjectIntegrationTextFixtureという力
ZenjectIntegrationTestFixture • このクラスを使うとできること ◦ PlayModeTestを実行するときにZenjectの権能を使うことができる • 具体的には… ◦ このクラスを継承すると、 [UnityTest]を実行するときにZenjectの権能が発揮される
◦ テスト実行時に3箇所のタイミングでZenjectの処理などを挟むことができる ◦ PlayModeTestなので、ContextやInstallerなどはすべて動作してくれる • ようするに、PlayModeTestでZenject使えるマン
ZenjectIntegrationTestFixture • これらを活用することで出来ること ◦ PlayModeTestでZenjectが動く!(語彙消失) ◦ PreInstallというメソッドを呼ぶ前に、 PlayModeで使うシーンを指定したり、シーンに操作が加えら れる ◦
PostInstallというメソッドを呼ぶ前に、テストに必要なバインド処理を記述できる つづく
ZenjectIntegrationTestFixture • これらを活用することで出来ること 2 ◦ PostInstallメソッドを呼んだ後、 Zenjectの処理がすべて起動する ◦ IInitializable.Initializeも呼ばれる ◦ このあとにテストが記述できる
◦ この瞬間はMonoVehaviour.Awakeのタイミングなので、 Startも呼ぶには一度yieldしておくこと つづく
ZenjectIntegrationTestFixture • つまりどういうことだってばよ ◦ 基本的なPlayModeTestの実行時に、Zenjectの全機能が起動可能 ◦ PostInstall前にバインド処理を自分で記述することで、 PlayModeTestでモックを参照させることも できる •
ところがどっこい、SceneTestのが強いので、こっちを使うのは稀かも?
SceneTestFixture…?
SceneTestFixtureという深淵 • こやつはいったい ◦ これを継承したクラスでも、 PlayModeTest時にZenjectの権能が使える ◦ Zenjectの神の力「StaticContext」を使うことで、Testするときに自在なパラメータを注入してしまう ことができる •
やばい
SceneTestFixtureヤバイ • やれることのベースはIntegrationTestと同じだが、思想が違う • テストのSetUpから権能を発揮しているので、自在にContextに操作が加えられる • StaticContextが所有するコンテナにBindを行うと、SceneContextが持つ InstallerでBindしたインスタンスを上書きしてBindされます • これを使うと・・・
SceneTestFixtureヤバイ • Zenjectで構築されたインゲームに対してデータ注入したテストができる ◦ 例:シューティングゲームで敵の速さを数段階設定、意図した結果になったかテスト ◦ 例の例:敵が弱い設定を注入したとき、プレイヤーは勝利する ◦ 例の例:敵が強い設定を注入したとき、プレイヤーは敗北する •
実データを投入したテストで、例外が出ないか検知するテストができる ◦ PlayModeTestを完全に使いこなすことで、自動テストを構築したのち ◦ 実データを投入、それを実行したときにエラーが出ないかテストできる ◦ 毎日回すとエラーが出たときにすぐ分かる!
Zenjectこそ神の意志
SceneTestFixtureヤバイ • 自動テストを構築しましょう ◦ まずはそこから。SceneTestFixtureを使ったテストを作成 ◦ 運用データを投入、たとえばゲームのホーム画面が出るまで、エラーが出ないことをテスト • Zenjectの権能で検証データを注入しましょう ◦
StaticContextの権能を使えば、あらゆる Containerに干渉できます ◦ 思いっきり検証用のデータを作りまくりましょう ◦ なんならマスターデータから自動でテストコードを作りましょう(真顔) • すると不思議、オートテストができる!!!
ちょっとまてや • 入力はどうすんだよ??? ◦ 悩みどころですね。Zenjectができるのはあくまで DIまで。 ◦ Zenjectが注入するオブジェクトはテストで自在に変えられますが、結局それまで。 ◦ テスト完全に理解した人たちなら、
PlayModeTestで入力をyieldで待つくらい出来るよ!
とはいえ凄い • テストコードを真面目に書くと感じると思うこと ◦ テストデータの用意がめんどう ◦ テストデータの依存解決も面倒 ▪ これはテストに限らないので、 Zenjectを使うわけですね
◦ Zenjectを使うとテストですら依存解決を Zenjectがしてくれる ◦ しかも、用意するテストデータは Bind時に個別につくればよい ▪ いっそテストケースごとに使うデータを全部 BindしてID指定もあり ▪ もちろんテストケースごとに Bind処理を書くのもあり ▪ データを用意することに注力できるのは、テスト工数の削減につながるねん
幻の第四のテスト
None
完全に理解した (わかってない)
User Driven Test Bedsって… • 手で動かしてねということ • 立派なテストです(と公式が言ってる) • 自動でできないのが難点・・・
• 見なかったことにしましょう
うまい感じに使うまとめ
まとめ • EditModeTestでZenjectを使いたいなら、UnitTestFixtureを使おう ◦ UnitTestと言ってるけどEditModeでIntegrationTestする場合も使える • PlayModeTestでは、まずはIntegrationTestFixtureを使おう ◦ 動作に慣れましょう。基本的には Play時と同じですが、PlayModeTestの書き方に慣れよう
• 自動でPlayModeTestを流したくなったそこのあなた、SceneTestを使おう ◦ 自動テスト環境の構築からはじめるんですけどね!!! ◦ 一度作ればユートピア、データを注入し放題〜〜〜
自動テスト環境を作れるほど テスト理解してたら 苦労しないよ・・・
〜FIN〜