Info on UNITY_INCLUDE_TESTS define

Hi, I am trying to figure out when UNITY_INCLUDE_TESTS define is… defined… and can’t seem to find any documentation in docs.unity3d.com. Could someone shed some light on it?

From the tests I’ve run it seems to always be defined in the editor whether just running a scene, or unit tests. And its not defined in any standalone builds. I am asking because I want to know if I can use this define to implement test time only setters, i.e.

// In MyGame.Runtime.asmdef
private int m_someInt;
public int SomeInt
{
    get { return m_someInt; }
#if UNITY_INCLUDE_TESTS
    set { m_someInt = value; }
#endif
}

Edit: It would also be good to know which Unity versions this is available in. For me they are available in 2018.4.11 & 2019.3.3.

1 Like

I was also hoping that UNITY_INCLUDE_TESTS was only defined when running the Test Runner, but this does not appear to be the case, as you mentioned. I have not yet found a way to differentiate between code that is being run from a test in Play Mode from code being run in the Editor normally.

In my case there is some initialization code that I don’t want/need to happen when running unit tests

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Create()
{
#if !UNITY_INCLUDE_TESTS
    // Initialization code for game only
#endif
}

We’ve also been hitting the same problem in trying to extend UTF.

In our scenario, we have a package that is split into Editor & Runtime components, both of which contain several helpers use in post result processing etc.

If I have the asmdef of both these components have a Define Constraints on ‘UNITY_INCLUDE_TESTS’, and they are in the Assets folder, irrespective of whether or not I’ve added UNITY_INCLUDE_TESTS to the scripting define symbols they are always included.

If I move this code to a local package, and keep the define constraints for both components, no matter what I do with UNITY_INCLUDE_TESTS, the code is never included. This define behaves incredibly sporadically; clarity would be helpful.

The insanely confusing thing is if I use some arbitrary (and made up) define in the exact same pattern, it behaves correctly. UNITY_INCLUDE_TESTS must behave similarly to this as it has the very critical aspect of including the NUnit.dll in the runtime.

1 Like

Hey. The purpose of UNITY_INCLUDE_TESTS is to signal whether an assembly contains tests. The constraint is added to the asmdef for the test assembly automatically when it is created. It is used by the build system to ensure that your tests does not get included in the player build, when building normally.

4 Likes

Thanks for the update. This at least explains how that value is intended to be used. I’m still unaware however of a way to check whether code is being run as part of a Play Mode test versus a normal play session in the editor.

1 Like

From our perspective, I’d amend that statement to include ‘whether an assembly contains tests, or UTF extension code’. Furthermore, it’s important to note that if we are speaking about a package containing theses tests (or again, in our case UTF extension code) it must be added to the testables dictionary of the consuming project’s manifest in order for it to behave idiomatically w.r.t. UNITY_INCLUDE_TESTS define.

I’ve wanted to have the same behaviour as OP so I’ve created a quick workaround for it.

I’ve defined my own constraint called TESTS_ENABLED

7495937--923087--upload_2021-9-15_0-6-2.png

Then I’ve added a static class with MenuItems that sets/removes this symbol in PlayerSettings.

using UnityEditor;

public static class TestMode
{
    public const string TESTS_ENABLED_SYMBOL = "TESTS_ENABLED";
 
    [MenuItem("Tools/Core/Tests/Set Test Mode (ON)")]
    public static void SetTestModeOn()
    {
        var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);

        symbols += SymbolString;
     
        PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, symbols);
    }
 
    [MenuItem("Tools/Core/Tests/Set Test Mode (OFF)")]
    public static void SetTestModeOff()
    {
        var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);

        symbols = symbols.Replace(SymbolString, string.Empty);
     
        PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, symbols);
    }

    private static string SymbolString
    {
        get
        {
            return $";{TESTS_ENABLED_SYMBOL}";
        }
    }
}

This way I can use it like this and have some encapsulation for fields that I don’t want to have modified by mistake from outside of components.

[SerializeField]
private bool _someProperty;

public bool SomeProperty
{
    get { return _someProperty; }
  
    #if TESTS_ENABLED
  
    set { _someProperty = value; }
  
    #endif
}

Please note to all Jetbrains Rider users: Have at least 3.0.1. version of the Rider package added to your project or it will not refresh the solution after using SetScriptingDefineSymbols. This is due to the bug that I’ve reported a year ago and was fixed in that version. (https://youtrack.jetbrains.com/issue/RIDER-49947?_ga=2.202255505.1048359544.1631644267-181869390.1631520501)

1 Like

As a little workaround, when in the editor you can check if the test runner is open.

if (EditorWindow.HasOpenInstances<UnityEditor.TestTools.TestRunner.TestRunnerWindow>())
{
    Debug.Log("Open");
}
else
{
    Debug.Log("Closed");
}

I’ve found a workaround that works in the editor and player. Basically you need to have a public static field/property somewhere in your main scripts assembly that defaults to “game mode”.

Then from within a [SetUp] or [OneTimeSetUp] method in your test code, set this static to whatever value you want to represent “test mode”.

Here’s the component that bootstraps my game

public class GameWorld : MonoBehaviour
{
    public static bool ReadyToStartGame = true;

    void Update()
    {
        if (!ReadyToStartGame)
            return;

        // other code that actually starts the game
    }
}

Then from within the test

public class TestClass
{
    [SetUp]
    public void SetUp()
    {
        GameWorld.ReadyToStartGame = false;

        // load scene and other stuff here
    }

    [UnityTest]
    public IEnumerator TestCode()
    {
        // any per-test setup logic

        GameWorld.ReadyToStartGame = true;

        // assertions for test here
    }
}

I’ve also ran into this right now. I created a new local package and all my tests do not show up. Furthermore, Rider doesn’t highlight/analyze the files in this assembly.

It does work when I remove the UNITY_INCLUDE_TESTS constraint. But I’ll eventually forget about that and all the test code ends up in the player, so I’m looking for a fix.

I double-checked the asmdefs and package.json of my other (local) packages where I have working unit tests or am able to quickly set them up. But I did not find a notable difference between them, they all also have the hideInEditor=false settings so that’s not it. Just this one package is affected and it’s only because of the constraint that the tests aren’t working/recognized.

UPDATE with fix:
I went to Preferences => External Tools and ticked almost all of the “Generate .csproj files for:” boxes. For me that meant ticking two additional boxes: the “Local tarball” and “Packages from unknown sources” checkboxes.

Then I closed Unity and Rider and deleted all .csproj and .sln files from the project folder.

After relaunching both Unity and Rider code analysis in test scripts is working and the tests show up in Test Runner. I bet this particular package must be considered to be “from an unknown source” for some reason (it’s not in a tarball).

In case this helps anyone, this is the package.json (location is the same base path as other local packages I use, in a subfolder named “GMesh”):

{
  "name": "com.codesmile.gmesh",
  "version": "0.1.0",
  "displayName": "CodeSmile GMesh",
  "description": "GMesh enables creating reliable geometry editing tools with Unity Job System support.",
  "category": "Tools",
  "unity": "2020.3",
  "dependencies": {
    "com.unity.burst": "1.7.3",
    "com.unity.collections": "1.4.0",
    "com.unity.jobs": "0.70.0-preview.7",
    "com.unity.mathematics": "1.2.6",
    "com.unity.test-framework.performance": "2.8.1-preview"
  },
  "relatedPackages": {},
  "samples": [
    {
      "displayName": "GMesh Examples",
      "description": "Some examples ...",
      "path": "Samples~/Scenes"
    }
  ],
  "keywords": [
    "mesh",
    "model",
    "graph",
    "edit",
    "asset",
    "tool",
    "editor"
  ],
  "author": {
    "name": "CodeSmile",
    "email": "<REMOVED>@gmail.com",
    "url": "https://github.com/sitterheim"
  },
  "hideInEditor": false
}

Hey,
For custom packages, have you tried adding them to the main project’s manifest as testables?
https://docs.unity3d.com/Manual/cus-tests.html

Yes in the meantime someone from Rider pointed that out. It‘s so easy to forget about that. The issue I was having was that tests did not show in Rider but worked fine in Unity.

I met the same problem,and your method not worked for me. To me this problem occupys when the local package is added into manifest file use file:…/xxx。If I copy the package to the packages folder, everything looks ok! I don’t know how to resolve this problem, and it’s ok when open with visual studio.

Find the solution : https://docs.unity3d.com/Manual/cus-tests.html#:~:text=Enabling%20tests%20for%20a%20package
Add the testables attribute because the local file package is not embedded