Skip to main content

Movable Objects Controller Test

Written by: Akram Taghavi-Burris | © Copyright 2024
Status

Testing is an essential part of the development process, as it ensures that our code behaves as expected and meets the requirements we set out to achieve. By identifying issues early, we can save time and effort in the long run, making it easier to maintain and expand our codebase.

Debug.Log Test

For our MovableObjectController, the first aspect we need to test is whether our movable objects are registering correctly. To accomplish this, we will implement Debug.Log messages that output to the console whenever a movable object is registered or unregistered. This approach will help us verify that our registration process is functioning as intended.

MovableObjectController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//Controller will inherent the Singleton pattern
public class MovableObjectController : Singelton<MovableObjectController>
{
// HashSet for all movableObjects (ensures uniqueness and faster lookup)
private HashSet<IMovable> _movableObjectRegistry = new HashSet<IMovable>();

// Registers a movable object (adds it to the HashSet if it's not already registered)
public void RegisterMovableObject(IMovable movableObject)
{
// Check if the object is not null and is not already registered
if (movableObject != null && !_movableObjectRegistry.Contains(movableObject))
{
// Add the object to the HashSet
_movableObjectRegistry.Add(movableObject);
Debug.Log($"{movableObject} has been registered.");
}//end If

}//end RegisterMovableObject()

// Unregisters a movable object (removes it from the HashSet if it's registered)
public void UnregisterMovableObject(IMovable movableObject)
{
// Check if the object is not null and is currently registered
if (movableObject != null && _movableObjectRegistry.Contains(movableObject))
{
// Remove the object from the HashSet
_movableObjectRegistry.Remove(movableObject);
Debug.Log($"{movableObject} has been unregistered.");

}//end If

}//end UnregisterMovableObject()

//continues...
}
C# String Interpolation

In Unity, you might commonly see Debug.Log used with concatenation, such as in the following example Debug.Log(movableObject.ToString() + " has been registered.");. However, the C# feature known as string interpolation, allows us to insert variable values directly into a string, for example Debug.Log($"{movableObject} has been registered."); This feature utilizes:

  • The dollar sign $ before the string indicates that the string will be interpolated.
  • {movableObject} is replaced with the string representation of the movableObject variable when the log message is generated.

Using string interpolation is often preferred for it's readability, but is considered a shorthand method, while concatenation if often more prevalently thought to beginners.

Testing with MovableObjectControllerTEST

As the game is still in its early development phase, many related systems have not yet been created or implemented. Despite this, the MovableObjectController encompasses a range of behaviors that we need to verify are set up correctly. Since other game systems are not in play at the moment, it's essential to devise an alternative method for testing these functionalities. By ensuring that the controller works as intended, we can identify any issues early in the process, which will ultimately facilitate easier maintenance and expansion of our codebase.

While we could implement some checks directly within the MovableObjectController, in this instance, we have chosen to separate the testing functionality into its own class, MovableObjectControllerTEST. This separation serves several purposes:

  • Focused Responsibility: By isolating testing logic in its own class, we keep the MovableObjectController focused solely on managing movable objects. This separation adheres to the Single Responsibility Principle, making each class easier to understand and maintain.

  • Simplified Testing: The MovableObjectControllerTEST class provides a straightforward method for triggering various functionalities of the MovableObjectController using key inputs. This approach allows us to quickly simulate user interactions and verify that each method behaves as intended during development.

  • Improved Debugging: With testing functionality housed separately, we can add and modify tests without cluttering the main controller code. This makes it easier to identify issues specific to testing and debugging without impacting the core functionality of the application.

Implementation

The MovableObjectControllerTEST class will be attached to a GameObject in the Unity scene and will reference an instance of the MovableObjectController. Within the Update() method, it will listen for specific key presses, each corresponding to a different action in the MovableObjectController.

Test Input

Unity's default input system will be used for testing to streamline the process and avoid the complexity of setting up the new Input System. This approach allows for rapid testing of the MovableObjectController's functionality with immediate feedback, making it easier to verify core actions without additional overhead.

In this instance we have mapped the following inputs for testing.

  • Stop All Movable Objects: Triggered by pressing S.
  • Resume All Movable Objects: Triggered by pressing R.
  • Reset All Movable Objects: Triggered by pressing T.
  • Update Speed for All Movable Objects: Triggered by pressing U.
  • Reverse Direction for All Movable Objects: Triggered by pressing D.

When a key is pressed, the relevant method will be invoked, and a log message will be printed to the console to confirm the action. This real-time testing approach allows for immediate feedback and interaction, making it easier to identify issues or verify functionality.

To ensure this script only runs in the Unity Editor and not in builds, you can wrap the functionality inside #if UNITY_EDITOR. This way, the script will execute in Play mode in the Editor but will be excluded from the build. By wrapping the class in #if UNITY_EDITOR, we ensure that the script is excluded from any builds, so the test functionality is only available during development in the Unity Editor.

The MovableObjectControllerTEST would be implemented as shown below and then attached to the same GameObject as the MovableObjectController. Once the class is attached, we can enter Play mode and use key presses to test the controller's functionality, ensuring that it responds as expected. This provides a straightforward way to validate the controller's behavior in a real-time game environment.

MovableObjectControllerTEST.cs
using UnityEngine;
#if UNITY_EDITOR
public class MovableObjectControllerTEST : MonoBehaviour
{
private void Update()
{
//Stop Check
if (Input.GetKeyDown(KeyCode.S)) // Stop all
{
MovableObjectController.Instance.StopAll();
Debug.Log("Stopped all movable objects.");
}//end Stop Check

//Resume Check
if (Input.GetKeyDown(KeyCode.R))
{
MovableObjectController.Instance.ResumeAll();
Debug.Log("Resumed all movable objects.");
}//end Resume Check

//Reset Check
if (Input.GetKeyDown(KeyCode.T))
{
MovableObjectController.Instance.ResetAll();
Debug.Log("Reset all movable objects.");
}//end Reset Check

//Update Speed Check
if (Input.GetKeyDown(KeyCode.U)) // Update speed
{
MovableObjectController.Instance.UpdateSpeedForAll(5f); // Example speed value
Debug.Log("Updated speed for all movable objects to 5.");
}//end Update Speed Check

//Reverse Direction Check
if (Input.GetKeyDown(KeyCode.D))
{
MovableObjectController.Instance.ReverseDirectionForAll();
Debug.Log("Reversed direction for all movable objects.");
}//end if Reverse Direction Check

}//end Update()
}
#endif
Unit Testing

While we created a dedicated MovableObjectControllerTEST class for testing, it's worth noting that we could have also leveraged Unit Testing and Unity's Test Framework, which would have been a more efficient and scalable practice for achieving similar goals. However, exploring those frameworks is beyond the scope of this lesson.

Summary

Verifying the functionality of the MovableObjectController by implementing a simple Debug.Log messages and recognizing the need for a dedicated testing solution, with MovableObjectControllerTEST class. This separate class enhances our testing capabilities by providing focused responsibility, simplified testing, and improved debugging. Additionally, we ensured that this test script only operates within the Unity Editor environment by wrapping it in #if UNITY_EDITOR directives, preventing it from being included in any builds.

With our testing framework in place, we can confidently ensure that the MovableObjectController operates as intended. Now, we will explore boundary management, adding another layer of control to prevent movable objects from going off-screen or moving into unintended areas. This system will further enhance our game's movement mechanics and overall structure.