# Testing

Based on Unity's test automation framework (more information can be found in the [Unity documentation](https://docs.unity3d.com/Packages/com.unity.test-framework@1.4/manual/index.html)), we have integrated a testing extension for our customers. All test scenes are defined in a scriptable asset, allowing you to extend tests by adding additional scenes as needed.

We provide two standard test tools:

1. **Counting Destroyed MUs on Sinks**: Verifies the number of Modular Units (MUs) destroyed on sinks.
2. **Counting MUs Passed on a Sensor**: Counts the number of MUs that pass through a sensor.

Please note that physics behavior may vary across different computers, so test results may differ between your machine and our testing environment.

The realvirtual.io test extension allows you to define tests without the need for programming custom scripts or logic.

## Prerequisites

By default, testing is not enabled as it requires additional Unity packages. To enable testing:

1. **Install Unity Test Framework**:

   * Install **Unity Test Framework Version 1.1.33** via the Unity Package Manager.

   <figure><img src="https://260262196-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpYxFg97YnJX96UzNNTSd%2Fuploads%2Fgit-blob-6d158367a49027ee0f9676e5921447ae117c230e%2Ftesting-packagemanager.png?alt=media" alt=""><figcaption><p>Installing Unity Test Framework via Unity Package Manager</p></figcaption></figure>
2. **Set Compiler Define**:

   * Navigate to **Project Settings** > **Player**.
   * Under **Scripting Define Symbols**, add `REALVIRTUAL_TESTS`.

   <figure><img src="https://260262196-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpYxFg97YnJX96UzNNTSd%2Fuploads%2Fgit-blob-eafc29537c02b31351ed8234da8ec9c764b9eae9%2Ftesting-projectsettings.png?alt=media" alt=""><figcaption><p>Enable testing in the Project Settings</p></figcaption></figure>

## Test window

After enabling testing as described above, follow these steps to run and manage your tests:

1. **Open the Test Window**:

   * Select **Testing** from the **realvirtual.io** main menu. This will open a new window displaying all defined tests.

   <figure><img src="https://260262196-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpYxFg97YnJX96UzNNTSd%2Fuploads%2Fgit-blob-12d74847cb20fdab3f962f34e5960ad77d385adc%2Ftesting-ok.png?alt=media" alt=""><figcaption><p>Testing window with successfull tests</p></figcaption></figure>
2. **View Test Status**:

   * Tests that have passed successfully will be indicated by green buttons.
   * Tests that have failed will be shown with red buttons, and a message will provide additional information.

   <figure><img src="https://260262196-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpYxFg97YnJX96UzNNTSd%2Fuploads%2Fgit-blob-028feba5a8671893e6f3d523c2fe2f9bf82eb72a%2Ftesting-failure.png?alt=media" alt=""><figcaption><p>Test window with failures</p></figcaption></figure>
3. **Run Tests**:
   * Click the **"Run Tests"** button to execute all defined tests.
   * If a test fails, you can select the test button to open the scene associated with the test.
4. **Filter Tests**:
   * You can define filters to narrow down the tests displayed.
   * When filters are applied, only the filtered tests will be executed when you select **"Run Tests"**.

## Defining your own tests

To define your own tests, follow these steps:

1. **Create a Test Scene List**:
   * In the Unity Project window, right-click in the desired project folder.
   * Select **Create** > **realvirtual** > **TestScenes** from the context menu.
2. **Default Test Scenes**:
   * The default test scenes provided are located under `realvirtual > private > Resources > Testing`.

Add each test scene you wish to include in your testing setup. For each scene listed, ensure the "Run Scene" checkbox is set to **true**. This setting specifies that the scene should be executed as part of the test process.

<figure><img src="https://260262196-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpYxFg97YnJX96UzNNTSd%2Fuploads%2Fgit-blob-17557b4e62302827db69ac898dc50dbda31a998e%2Ftesting-demoscenescriptableasset.png?alt=media" alt=""><figcaption><p>Standard test scenes</p></figcaption></figure>

The testing window will automatically detect all **Test Scene List** assets in your project.

## Preparing a Scene for Tests

To prepare a scene for testing, you need to include a **Test Model Controller** in each test scene. You can add this controller to your project by using the prefabs located under `realvirtual > private > Resources > Testing`.

**Test Model Controller**

The **Test Model Controller** manages several test parameters:

* **Run Test**: Determines if the test should be executed.
* **TimeScale**: Adjusts the speed at which the test runs, allowing it to run faster or slower than real time.
* **Test Time**: Specifies the duration of the test in seconds.
* **Fixed Timestep**: Sets the fixed timestep to be used during the test.

You can manually start the test by selecting **Run Test** (this applies only to the current scene). The **Test Model Controller** will also call all methods implementing the `ITestCheck` interface.

**Standard `ITestCheck` Implementations**

We provide two standard implementations of the `ITestCheck` interface:

* **TestSensorCount**: Counts the Modular Units (MUs) passing through sensors where `TestSensorCount` is attached. The **Test Model Controller** automatically checks all `TestSensorCount` components in the scene.
* **TestSinkCount**: Counts the MUs destroyed by sinks where `TestSinkCount` is attached. The **Test Model Controller** automatically checks all `TestSinkCount` components in the scene.

## Implementing Your Own `ITestCheck`

To create a custom `ITestCheck` implementation, follow these steps:

1. **Create a New MonoBehaviour**: Implement the `ITestCheck` interface in a new MonoBehaviour script.
2. **Implement the `Check` Method**: Define the `Check` method to return an empty string if the test is successful, or a descriptive message if the test fails.

Here's a sample implementation of a custom `ITestCheck` for counting sensor events:

```csharp
namespace realvirtual
{
    using NaughtyAttributes;
    using UnityEngine;

    public class TestSensorCount : MonoBehaviour, ITestCheck
    {
        [InfoBox("This is just for internal realvirtual.io Development and Test automation", EInfoBoxType.Warning)]
        public int DueSensorCount;  // Expected count of MUs passing the sensor

        public int Tolerance = 0;  // Allowed tolerance in the count

        public string Check()
        {
            // Get the current count of MUs passing the sensor
            var counter = GetComponent<Sensor>().Counter;
            
            // Calculate the difference between the expected and actual count
            int difference = Mathf.Abs(counter - DueSensorCount);

            // Check if the count is within the allowed tolerance
            if (difference <= Tolerance)
            {
                return "";  // Test passed
            }
            else
            {
                // Return a descriptive failure message
                if (Tolerance == 0)
                    return "Sensor count at " + this.name + " is " + counter + " but should be " + DueSensorCount;
                else
                    return "Sensor count at " + this.name + " is " + counter + " but should be within " + Tolerance + " of " + DueSensorCount;
            }
        }
    }
}
```

#### Key Points

* **Attach to Component**: You can attach this script to any relevant component in your scene.
* **Automatic Invocation**: The `Check` method will be called automatically by the `Test Model Controller` once the test time is finished.
* **Success and Failure**: Return an empty string for a successful test or a descriptive message if the test fails.

By implementing your own `ITestCheck` classes, you can extend the testing capabilities to fit your specific needs.
