63

I created the following structure:

├── Assets
├── Scenes
├── Scripts
│   └── MyExample.cs
├── Tests
│   ├── MyExampleTest.cs
│   └── Tests.asmdef

Now, when I click on Run All, in the Test Runner window, in Unity, I have the following error:

The type or namespace name `MyExample' could not be found. Are you missing an assembly reference?

In Visual Studio I have two projects:

  • Assembly-CSharp (containing src)

  • Tests (containing Tests)

I added Assembly-CSharp as a reference in the second project. Visual Studio is able to build the solution with no errors.

Does anyone know how to properly setup a UnitTest regression for a Unity project?

This is Tests.asmdef

{
    "name": "Tests",
    "optionalUnityReferences": [
        "TestAssemblies"
    ]
}

MyExampleTest.cs

using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;
using abc;

public class MyExampleTest{

    [Test]
    public void NewTestScriptSimplePasses() {
        // Use the Assert class to test conditions.
    }

    [UnityTest]
    public IEnumerator NewTestScriptWithEnumeratorPasses() {
        abc.Example m;
        Assert.That(false);
        yield return null;
    }
}

MyExample.cs

namespace abc
{
    public class Example
    {


    }
}
sonnyb
  • 3,194
  • 2
  • 32
  • 42
HAL9000
  • 3,562
  • 3
  • 25
  • 47
  • Which version of Unity are you using? Just in case, does your Tests.asmdef file reference test assemblies that are editor only? Otherwise, note that Unity unit tests need to be in an Editor folder. – sonnyb May 08 '18 at 13:46
  • @sonny I update the question with the file Tests.asmdef. Unity version 2018.1.0f2 – HAL9000 May 08 '18 at 13:59
  • It looks like that adding the reference within Visual Studio is ineffective in Unity. When I close and reopen the reference is not set anymore – HAL9000 May 08 '18 at 14:02

4 Answers4

64

Try using the built-in Test Runner UI to set-up your Test Assembly Folder and first Test script.

Use Window -> Test Runner -> EditMode -> "Create Test Assembly Folder", and once you navigate to the new Test Assembly Folder, use the Create Test Script in current folder button.

In particular, your Tests.asmdef is missing an "Editor" include compared to the default setup (in Unity 2018.1).

{
    "name": "Tests",
    "optionalUnityReferences": [
        "TestAssemblies"
    ],
    "includePlatforms": [
        "Editor"
    ]
}

You should not have to do anything manually in Visual Studio project for the purpose of setting up your tests.

Note that when my Assembly File is set to "Any Platform" as follows (like in your question):

{
    "name": "Tests",
    "optionalUnityReferences": [
        "TestAssemblies"
    ]
}

My tests do not show up in the Test Runner window.

When my Assembly File is explicitly set to include "Editor" platform only (as per my previous example), my tests show up correctly in the Test Runner window.

(This behaviour seems a bit counterintuitive to me.)


You also need to set up an Assembly Definition for your scripts. Under your Scripts, folder, create an assembly definition file MyScriptAssembly.asmdef (using the Unity menu Assets -> Create -> Assembly Definition or manually):

{
    "name": "MyScriptAssembly"
}

Then, make sure your Tests.asmdef reference your script Assembly:

{
    "name": "Tests",
    "references": [
        "MyScriptAssembly"
    ],
    "optionalUnityReferences": [
        "TestAssemblies"
    ],
    "includePlatforms": [
        "Editor"
    ],
    "excludePlatforms": [],
    "allowUnsafeCode": false
}

You can also set this up in the Unity Editor inspector window. See 'References' in the Inspector when selecting a .asmdef file:

assembly definition inspector window

(For more details, see Unity's documentation on assembly definition files)

sonnyb
  • 3,194
  • 2
  • 32
  • 42
  • thanks for helping. I created a new Tests folder following your procedure: I still have the same compilation error. The empty test is working fine, but I can't use my Example class – HAL9000 May 08 '18 at 15:41
  • Maybe it's something specific to your MyExample.cs and MyExampleTest.cs. Could you update your question with the code for those files? – sonnyb May 08 '18 at 15:56
  • I think the problem is somewhere in how Unity creates the projects references. I updated the question – HAL9000 May 08 '18 at 16:10
  • @HAL9000 I've updated my answer. I'm not very familiar with the new Assembly Definition feature in Unity, but hopefully this will fix your issue. – sonnyb May 08 '18 at 16:33
  • @HAL9000 without the assembly reference, I get the same error as you (`error CS0246: The type or namespace name [...] could not be found. Are you missing an assembly reference?`), but it's a compile-time error, and when I click "Run All" it logs an error message saying `Fix compilation issued before running tests` ["issued (sic)" typo] – sonnyb May 08 '18 at 16:39
  • 2
    I had some other strange error. I re-created the project, following your advise and, finally, it's working. I really thank you :) The problem was with the missing Assembly definition. – HAL9000 May 08 '18 at 16:48
  • 3
    Thank you for this great answer! – rennat Dec 01 '18 at 21:38
  • 1
    Setting up an AssemblyDefinition within myScripts folder appears to break my scripts (who for some unknown reason can't find each other now) and doesn't show up in the Inspector for the Test.asmdef -> Assembly References when I click + and scroll around. – Noah Ternullo Mar 02 '20 at 02:07
23

Finally found the right proper solution for this. And everything is done through the Editor.

So our goal is to have the test assembly reference the real-code assembly. In order to do that you need to define both assemblies and then set up the reference in unity.

  1. Create your tests as usual from inside Unity. With the generation of the assembly.
  2. Go to your scripts folder (usually Assets/Scripts) and right click -> Create Assembly definition this will create an assembly file in there as well.
  3. Go to your tests assembly info in Unity and add a reference to your real assembly and also make sure that it's only marked for the Editor platform.

You're set. Your tests should be visible and runnable in Unity and they can reference any other script.


Keep in mind that you are safe to delete ALL .csproj and .sln files in the root folder and Unity will recreate them (also they should not be on source control).

So your test to go for changes like that should always be to

  1. Delete any visual studio related file in the folder.
  2. Select Assets -> Open C# project. Let it do its thing.
  3. If everything compiles and runs and your tests do so as well you've set things up nicely.

Bonus: We also have a couple of debug projects in our project which are located in Assets/DebugScenes/DebugScripts. By creating a separate assembly for them and have it reference the real scripts assembly (if needed) and marking it as Editor platform we make sure these scripts are never included in our build without any extra steps during build.


Extra reading. You might be thinking that you don't want to create an assembly for ALL your scripts since you only want to test some of them. And it's true you can create an assembly for a subfolder but this will get you into trouble as then you have to create a reference from one real scripts assembly to another. So make sure everything is nice and tidy and makes sense...


Our test and real script assembly infos side-by-side. Game Title has Planetary in it

  • 1
    When I add assembly definition to my scripts, it complains that "OVRInput" (which is an occulus rift class) does not exist under the current context. It's not obvious how to force Unity to add a reference to the related OVR dll. – Kamran Bigdely Apr 19 '19 at 22:19
  • In the new unity (2019.1) there is an extra flag in the assembly definition which is "include in the default assembly" or something along those lines. It's not shown in the pictures above as it didn't exist back then. Try enabling that on your OV assembly definition. – Thanasis Kapelonis Apr 20 '19 at 20:07
  • 1
    This seems to dont work if you have Editor subfolder in the Script folder. I guess I have to create 2 assembly definition, 1 for engine, 1 for editor. But it is very painful to change all my hierarchy to do that, any solution out there ? – Flavien Marianacci Jan 02 '20 at 10:07
  • 1
    If i add a `Assembly definition`, the test find my scripts, but almost every script will not work anymore due to assembly new reference errors (e.g. "The type or namespace name 'UnityEngine' could not be found (are you missing a using directive or an assembly reference?)". I tried some options like `Auto Referenced` but nothing helped. Unity 2020.3 – tturbo Jan 13 '23 at 09:17
  • Thank you very much. But this workflow is very hard in a big project which have several modules and plugins. We had to set AssemblyDefinition for every part. Without autoreference, it's hard enough for us to drop the unity-testframework. We create a lightweight alternative. And is there any one have better ideas? – user890054 May 05 '23 at 12:20
15

Lite, "zero assemblies", alternative setup:

Assets
├── Scenes
├── Scripts
│   └── MyGameScript.cs
├── Editor
│   └── MyGameScriptTests.cs

All the scripts inside Editor directory can reference NUnit.Framework namespace and these tests will show up in Test Runner window.

It's main advantage is simplicity. I'm sure there are drawbacks somewhere, but for everyday projects, it's a blessing; zero hassle to set it up, just works.

Andrew Łukasik
  • 1,454
  • 12
  • 19
  • 4
    Oh, shoot! Yea, this works great. My one complaint would be that it seems like you can't run PlayMode Tests, which is a frustrating drawback. – Will Lacey Aug 26 '21 at 15:47
  • And the tests would probably end up bundled in the final build with other code. – Štefan Schindler Nov 25 '21 at 03:27
  • 3
    @ŠtefanSchindler Fortunately "Editor" directory scripts are excluded from builds. – Andrew Łukasik Nov 25 '21 at 07:10
  • The main issuse, that i can not reference `MyGameScript.cs` from `MyGameScriptTest.cs` is still present with this solution. Unity 2020.3 – tturbo Jan 13 '23 at 09:19
  • 1
    @tturbo With unity test framework 1.1.33, Unity Editor 2021.3.25f1 or 2022.3.7f1 I can reference the scripts in Scripts folder (or its subfolders) from the scripts in Editor folder (or its subfolders) – Helder Daniel Aug 20 '23 at 09:43
  • 1
    Probably the easiest way to setup Editor mode tests, thanks. I did not find any drawbacks while I used it. – Helder Daniel Aug 23 '23 at 14:00
0

Andrew Lukasik's answer is probably the simplest solution regarding Editor mode tests. It does not require assemblies.

However, I could not find a way to setup Play mode tests in a similar way, without assemblies.

An easy way to setup Play mode unit testing for scripts distributed by many folders is suggested in this answer: Create just one assembly definition in the root of the Scripts folder.

Note: A similar procedure can be used to setup also Editor mode tests.
The full procedure:

  1. Create a Folder for tests from the Test runner, eg: Assets/Test/PlayMode
    An assembly will be created in that folder: PlayMode.asmdef

  2. Now, create just another assembly, in the root of the scripts folder, eg.: Assets/Script/scripts.asmdef, using menu option:

Assets > Create > Assembly definition

  1. Select the assembly definition in the play mode test folder, PlayMode.asmdef, then in the Inspector, field Assembly Definition References, add the Scripts root assembly: scripts.asmdef.

enter image description here

If Unity Editor issues an error stating that one or more namespaces are missing, eg: "new Input System" namespace, use the procedure in this answer:

  • select the assembly definition in the root of the scripts folder, scripts.asmdef,
  • in the Inspector, field Assembly Definition References, add the missing namespaces, eg: Unity.InputSystem

enter image description here

Helder Daniel
  • 331
  • 3
  • 8