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とテスト
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
いも
March 20, 2018
Programming
8.4k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Zenjectとテスト
Gotanda.unity #5で発表するやつです
いも
March 20, 2018
More Decks by いも
See All by いも
UnityプログラミングバイブルR6号宣伝&Unity Logging小話
adarapata
0
640
Unityテスト活動のふりかえり
adarapata
1
690
Gather.townはいいぞ その後
adarapata
1
1.7k
Unityでの開発事例
adarapata
3
23k
どこのご家庭にもあるシーンマネージャーの話
adarapata
2
8.8k
Gather.townはいいぞ
adarapata
2
2.4k
宴はいいぞ
adarapata
0
2.2k
わかった気になるモブプログラミング
adarapata
1
180
モブワークっぽいのをやっている話/Trying mobwork
adarapata
2
1.3k
Other Decks in Programming
See All in Programming
実装をデザインガイドラインに追従させるための取り組み / 260731-dip-mosh-design-system
dachi023
0
1.8k
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
2
300
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
4
460
ドリフトを絶対に許さない(?)CDK運用 / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
200
仕様駆動開発の消費期限
watany
20
8.6k
Foundation Models frameworkで画像分析
ryodeveloper
1
620
Google Apps Script で Ruby を動かす
kawahara
0
260
【やさしく解説 設計編・中級 #6】良いアーキテクチャとは ~ 一本の登り道の、行き先 ~
panda728
PRO
0
220
【QA Test Talk Vol.8】AI-DLC による Whole Team Approach の加速
pkshadeck
PRO
0
190
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
210
バグを直したら useEffect が消えた
colorful12
2
540
これって Effect でできたのでは? / TSKaigi Mashup Kansai #2
susisu
0
240
Featured
See All Featured
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
How to build a perfect <img>
jonoalderson
1
5.9k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.3k
30 Presentation Tips
portentint
PRO
1
370
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
540
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
300
A Soul's Torment
seathinner
6
3.4k
Agile that works and the tools we love
rasmusluckow
331
22k
Docker and Python
trallard
47
4.1k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
400
Transcript
Zenject でのテスト Gotanda.unity #5 2018/03/20
自己紹介 いも(@adarapata) ミクシィ XFRAG ゲー ムプログラマ 入社三日目 最近GodotEngine が楽しい
今日の内容 Unity 標準のテストの書き方と、Zenject を使って いる場合のテストの書き方の違いを知る。 ※ Unity 内でのテストコー ドが必要かどうかについて は今回は話しません。
Zenject is https://github.com/modesttree/Zenject Unity で使えるDI フレー ムワー ク 依存関係をすっきりさせてくれる かせさんの記事がわかりやすい
http://yutakaseda3216.hatenablog.com/entry/201 7/04/17/124612
Unity のTest 書いてますか?
Unity でのテスト方法 EditModeTest エディタ上で動くテスト PlayModeTest シー ン上で動作確認できるテスト
Zenject in Unity でのテスト方 法 EditModeTest == Zenject Unit Test
エディタ上で動くテスト PlayModeTest == Zenject Integration Test シー ン上で動作確認できるテスト
Foo がIBar に依存してる処理( 通常) public class Foo { public IBar
bar; public int CallBar() // このメソッドをテストしたい { return bar.Bar() * 2; } } public interface IBar { int Bar(); }
EditModeTest public class FooEditModeTest { class MockBar : IBar {
public int Bar() { return 5; } } [Test] public void CallBarTest() { Foo foo = new Foo { bar = new MockBar() }; Assert.AreEqual(10, foo.CallBar()); } } Foo に流し込むモック用クラスを作る必要がある
Foo がIBar に依存してる処理 (Zenject) public class Foo { [Inject] public
IBar bar { get; private set; } public int CallBar() // このメソッドをテストしたい { return bar.Bar() * 2; } } public interface IBar { int Bar(); }
[TestFixture] public class FooUnitTest : ZenjectUnitTestFixture { [Test] public void
CallBarTest() { var mock = new Mock<IBar>(); mock.Setup(b => b.Bar()).Returns(5); Container.BindInstance(mock.Object); Container.Bind<Foo>().FromNew().AsSingle(); var foo = Container.Resolve<Foo>(); Assert.AreEqual(10, foo.CallBar()); } } Container 経由でインスタンスを生成できる Container のモック機能が使える
Mock<T> 便利 Moq ライブラリが提供する機能 https://github.com/moq モックを簡単に流し込めるのでテストが楽 OptionalExtras に入ってる // 何も返さなくていいとき
Container.Bind<IBar>().FromMock() // 明示的にメソッドの返り値をモックしたい時 var mock = new Mock<IBar>(); mock.Setup(b => b.Bar()).Returns(5); Container.BindInstance(mock.Object);
MonoBehavior が必要な処理 public class SpaceShip : MonoBehaviour { public Vector3
Velocity { get; set; } public void Update() { transform.position += Velocity * Time.deltaTime; } } Velocity が設定されたら動くかテストしたい
public class SpaceShipPlaymodeTest { [UnityTest] public IEnumerator SpaceShipPlaymodeTestWithEnumeratorPasses var spaceShip
= new GameObject("ship") .AddComponent<SpaceShip>(); spaceShip.Velocity = Vector3.up; Assert.AreEqual(spaceShip.transform.position, Vector3.ze yield return new WaitForSeconds(1F); Assert.Greater(spaceShip.transform.position.y, 0F); } }
MonoBehavior が必要な処理(Zenject) public class SpaceShip : MonoBehaviour { [Inject] public
Vector3 Velocity { get; private set; } public void Update() { transform.position += Velocity * Time.deltaTime; } }
Zenject in PlayMode public class SpaceShipTests : ZenjectIntegrationTestFixture { [UnityTest]
public IEnumerator TestVelocity() { PreInstall(); Container.Bind<SpaceShip>() .FromNewComponentOnNewGameObject() .AsSingle().WithArguments(Vector3.up); PostInstall(); var spaceShip = Container.Resolve<SpaceShip>(); Assert.AreEqual(spaceShip.transform.position, Vector3.ze yield return null; Assert.Greater(spaceShip.transform.position.y, 0F); } }
ZenjectIntegrationTestFixture がDI するためにいい感 じのメソッドを持っている PreInstall テスト用の準備をしてくれる Validation とかContext の生成とか PostIntall
バインドしたオブジェクトを注入する Run all in player には対応しておらず実機では走 らないので注意
所感 普通のテストとそんなにやり方は変わらない Zenject で書くべき! というかはInject してたら必 然的にテストもContainer 使わざるを得なくなるよ ねというお気持ち でもMoq
をサクッと使えるのは便利かも
余談1 unity-uitest https://github.com/taphos/unity-uitest uGUI 周りのテストを書きやすくしてくれるライブ ラリ クリックイベント辺りをやりやすくしてくれる UITest を継承する必要があるので ZenjectIntegrationTest
だと使いづらい
public class TestExample : UITest { [UnityTest] public IEnumerator Example()
{ // シー ン読み込み yield return LoadScene("TestableScene"); // Button オブジェクトを押したことにする yield return Press("Button"); // Foo/Text のラベルの文字を確認する yield return AssertLabel("Foo/Text", "Pressed!"); yield return Press("Close"); // FooWindow コンポー ネントがついたオブジェクトが非アクティブになる yield return WaitFor(new ObjectDisappeared<FooWindow>( } }
余談2 RuntimeUnitTestToolkit https://github.com/neuecc/RuntimeUnitTestToolkit @neuecc さんの作ったテストライブラリ 普通のシー ン上でテストを走らせてくれる アサー ションを再実装してシー ンで動くようにし
ている シー ン上での動作なので実機での確認も可能
None