Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by OperationT · Apr 17, 2016 at 11:42 AM · touchtestingnunit

Creating Test Doubles for Unity3D Objects

After making my classes collaborate passively (i.e. objects that the class uses are passed in at instantiation) so that I could unit test them, I realized that I cannot create test doubles (e.g. test stubs) for UnityEngine objects (such as Touch) that are passed into the class under testing (see NSubstitute Docs). As stated in the NSubstitute documentation, substitution only works with interfaces, or objects' virtual/abstract members.

I wanted to pass in a Touch with Touch.phase = TouchPhase.Began, and Touch.position = new Vector2(1.0f, 1.0f) to the class under testing, which does something with the Touch object. Because Touch.phase and Touch.position are not virtual/abstract, I cannot substitute for them and set a return value with NSubstitute. Of course, they are read-only fields as well, so I cannot set their values at instantiation.

Is it not possible to unit test methods that consume UnityEngine objects? If it is, what are my option(s) in doing so, and how does one go about in performing such option(s)?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Statement · Apr 17, 2016 at 12:34 PM

I recently tested input logic, although I was testing code that was using UnityEngines EventSystem functionality. Regardless, the same problem we both get is that the code becomes untestable due to depending on runtime user input.

What I did was decouple the logic code from the input types. This creates a class that contains logic, that is testable and then my component class feeds the logic the data from the input. If you need more data, consider making a class or struct and pass that into your methods.

 public class TestableLogic // tested
 {
     public void OnDown(int pointerId, Vector2 position) { ... }
 }
 
 public class UntestableInputLogic : MonoBehaviour, IPointerDownHandler // not tested
 {
     TestableLogic t = new TestableLogic();
     public void OnPointerDown(EventSystems.PointerEventData eventData)
     {
         t.OnDown(eventData.pointerId, eventData.position); // pass the data I need
     }
 }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Statement · Apr 17, 2016 at 12:35 PM 0
Share

It might be possible to actually test the code creating a PointerEventData, but it required an EventSystem in the constructor and I decided to just keep it simple in the face of unknowns at the time.

avatar image
2

Answer by BoraHorzaGobuchul · Apr 18, 2016 at 01:30 PM

@OperationT: As @Statement illustrates, the Unity3D api is easy to use but usually impossible to unit test. I have tried to apply Test Driven Development (TDD) whenever I can in Unity3D, but sometimes it is just not worth the stress. So with a simple FPS with little logic, I just have manual tests. But ... if I start to develop a game with a significant amount of logic/AI (e.g. simulations like Conway's Game Of Life) then I will ignore Unity and create the AI without any reference to any UI at all. This turns the problem the right way up - not 'how do adapt my code to Unity' but 'how do I adapt Unity to my code' ? This way you can easily and safely modify the AI as you add each new feature - TDD is more about flexible design than functional testing. For ideas on how to deal with difficult-to-test APIs, have a look at Micheal Feathers' "Working Effectively With Legacy Code", chapter "My Application Is All API Calls".

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

NUnit and VisualStudio 2 Answers

Asynchronous unit testing 1 Answer

NUnit delayed constraint does not appear to work in playmode test 0 Answers

Unity test tool simulate holding key ? 0 Answers

NUnit difference between Assert's IsTrue/IsFalse and True/False 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges