- Home /
How to run tests that require Input?
Hello, so resently I downloaded unity testing tools and since I heard/read that they are so useful I desided to make a TDD project.
But I have a question:
How do I make integration tests that require input?
Like when the player presses the left arrow the character turns left? Or when the player kills 10 enemies the game ends?
Answer by Barbog · Jul 29, 2015 at 07:46 PM
Essentially, you don't. What you'll be wanting to do is to decouple your code from the actual input and instead rely on the results of the input. This can be done by separating all the non-Unity API code from that which does use the Unity API and then put a layer in-between the two. Then you can have a test object in your integration test which takes the place of the actual input. The Unity team has a great blog post which goes into similar types of decoupling in decent detail here
I know this is kinda old post, but I would like to give my input (bad pun) on cgeopapa's post and your answer. I do understand your point. Logic should be extracted from $$anonymous$$onoBehaviour objects and tested as unit tests.
However, I feel like cgeopapa's point is still valid. It is good to know every class is working individually but if you want to test the interaction between components (basically integration testing), you might want to simulate user input. Not everything can be tested as unit tests. Why can this be useful? I would like to give a simple example: Let say I have this code sample which makes my character jumps when space key is pressed: void Update() { if(Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space)) { character.jump(); } }
Here, all the logic regarding the jump is in the method jump of Character (Can he jump? Is he grounded?, etc...) However, if I delete the line character.jump();
accidently, my character won't jump anymore when the space key is entered. I would like to be notified by a failing test on this because I really want my character to jump when it happens.
I would like Unity Test Tools to have a way to create inputs (something like "at X seconds, for y seconds, simulate keydown). Right now, you could do your own wrapper around Unity input (like shown on this post) but I don't feel it is a good idea to change your code only to test. Some might say that you change code only for testing purposes when you do this, but I feel it is more like a good practice to allow maintanable code by separation responsabilities.
For best results you'd eventually want to write centralized Input $$anonymous$$anagers, which should only be tested once. Everything else should be written on top of that and test it's own logic and not input.