Search Unity

Info on UNITY_INCLUDE_TESTS define

Discussion in 'Documentation' started by mbatutis, May 14, 2020.

  1. mbatutis

    mbatutis

    Joined:
    Jan 3, 2017
    Posts:
    4
    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.
    Code (CSharp):
    1. // In MyGame.Runtime.asmdef
    2. private int m_someInt;
    3. public int SomeInt
    4. {
    5.     get { return m_someInt; }
    6. #if UNITY_INCLUDE_TESTS
    7.     set { m_someInt = value; }
    8. #endif
    9. }
    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.
     
    Last edited: May 14, 2020
    EmberLuis likes this.
  2. EmberLuis

    EmberLuis

    Joined:
    May 22, 2019
    Posts:
    11
    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
    Code (CSharp):
    1. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    2. private static void Create()
    3. {
    4. #if !UNITY_INCLUDE_TESTS
    5.     // Initialization code for game only
    6. #endif
    7. }
     
  3. Julian_Gamble

    Julian_Gamble

    Joined:
    Feb 26, 2020
    Posts:
    7
    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.
     
    CodeSmile likes this.
  4. Warnecke

    Warnecke

    Unity Technologies

    Joined:
    Nov 28, 2017
    Posts:
    92
    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.
     
    KyryloKuzyk, guywald and RunninglVlan like this.
  5. EmberLuis

    EmberLuis

    Joined:
    May 22, 2019
    Posts:
    11
    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.
     
    hamza_unity995 likes this.
  6. Julian_Gamble

    Julian_Gamble

    Joined:
    Feb 26, 2020
    Posts:
    7
    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.
     
  7. Syganek

    Syganek

    Joined:
    Sep 11, 2013
    Posts:
    85
    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


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

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


    Code (CSharp):
    1. using UnityEditor;
    2.  
    3. public static class TestMode
    4. {
    5.     public const string TESTS_ENABLED_SYMBOL = "TESTS_ENABLED";
    6.  
    7.     [MenuItem("Tools/Core/Tests/Set Test Mode (ON)")]
    8.     public static void SetTestModeOn()
    9.     {
    10.         var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
    11.  
    12.         symbols += SymbolString;
    13.      
    14.         PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, symbols);
    15.     }
    16.  
    17.     [MenuItem("Tools/Core/Tests/Set Test Mode (OFF)")]
    18.     public static void SetTestModeOff()
    19.     {
    20.         var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
    21.  
    22.         symbols = symbols.Replace(SymbolString, string.Empty);
    23.      
    24.         PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, symbols);
    25.     }
    26.  
    27.     private static string SymbolString
    28.     {
    29.         get
    30.         {
    31.             return $";{TESTS_ENABLED_SYMBOL}";
    32.         }
    33.     }
    34. }
    35.  
    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.

    Code (CSharp):
    1. [SerializeField]
    2. private bool _someProperty;
    3.  
    4. public bool SomeProperty
    5. {
    6.     get { return _someProperty; }
    7.  
    8.     #if TESTS_ENABLED
    9.  
    10.     set { _someProperty = value; }
    11.  
    12.     #endif
    13. }
    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/issu...05.1048359544.1631644267-181869390.1631520501)
     
    Julian_Gamble likes this.
  8. Jaden_01

    Jaden_01

    Joined:
    Jan 5, 2020
    Posts:
    12
    As a little workaround, when in the editor you can check if the test runner is open.

    Code (CSharp):
    1. if (EditorWindow.HasOpenInstances<UnityEditor.TestTools.TestRunner.TestRunnerWindow>())
    2. {
    3.     Debug.Log("Open");
    4. }
    5. else
    6. {
    7.     Debug.Log("Closed");
    8. }
     
  9. jaydenm

    jaydenm

    Joined:
    Nov 16, 2018
    Posts:
    11
    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
    Code (CSharp):
    1. public class GameWorld : MonoBehaviour
    2. {
    3.     public static bool ReadyToStartGame = true;
    4.  
    5.     void Update()
    6.     {
    7.         if (!ReadyToStartGame)
    8.             return;
    9.  
    10.         // other code that actually starts the game
    11.     }
    12. }
    Then from within the test
    Code (CSharp):
    1. public class TestClass
    2. {
    3.     [SetUp]
    4.     public void SetUp()
    5.     {
    6.         GameWorld.ReadyToStartGame = false;
    7.  
    8.         // load scene and other stuff here
    9.     }
    10.  
    11.     [UnityTest]
    12.     public IEnumerator TestCode()
    13.     {
    14.         // any per-test setup logic
    15.  
    16.         GameWorld.ReadyToStartGame = true;
    17.  
    18.         // assertions for test here
    19.     }
    20. }
     
  10. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,975
    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"):
    Code (CSharp):
    1. {
    2.   "name": "com.codesmile.gmesh",
    3.   "version": "0.1.0",
    4.   "displayName": "CodeSmile GMesh",
    5.   "description": "GMesh enables creating reliable geometry editing tools with Unity Job System support.",
    6.   "category": "Tools",
    7.   "unity": "2020.3",
    8.   "dependencies": {
    9.     "com.unity.burst": "1.7.3",
    10.     "com.unity.collections": "1.4.0",
    11.     "com.unity.jobs": "0.70.0-preview.7",
    12.     "com.unity.mathematics": "1.2.6",
    13.     "com.unity.test-framework.performance": "2.8.1-preview"
    14.   },
    15.   "relatedPackages": {},
    16.   "samples": [
    17.     {
    18.       "displayName": "GMesh Examples",
    19.       "description": "Some examples ...",
    20.       "path": "Samples~/Scenes"
    21.     }
    22.   ],
    23.   "keywords": [
    24.     "mesh",
    25.     "model",
    26.     "graph",
    27.     "edit",
    28.     "asset",
    29.     "tool",
    30.     "editor"
    31.   ],
    32.   "author": {
    33.     "name": "CodeSmile",
    34.     "email": "<REMOVED>@gmail.com",
    35.     "url": "https://github.com/sitterheim"
    36.   },
    37.   "hideInEditor": false
    38. }
     
    Last edited: Aug 14, 2022
  11. kalman_balint

    kalman_balint

    Unity Technologies

    Joined:
    Jun 29, 2022
    Posts:
    1
  12. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,975
    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.
     
  13. lwangwangl

    lwangwangl

    Joined:
    Apr 6, 2016
    Posts:
    13
    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.
     
  14. lwangwangl

    lwangwangl

    Joined:
    Apr 6, 2016
    Posts:
    13