HAL9000
HAL9000

Reputation: 3751

How to set up unit tests in Unity and fix missing assembly reference error?

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:

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
    {


    }
}

Upvotes: 69

Views: 37280

Answers (4)

Helder Daniel
Helder Daniel

Reputation: 411

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

Upvotes: 2

Andrew Łukasik
Andrew Łukasik

Reputation: 1637

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.

Upvotes: 17

sonnyb
sonnyb

Reputation: 3504

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)

Upvotes: 69

Thanasis Kapelonis
Thanasis Kapelonis

Reputation: 1177

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

Upvotes: 26

Related Questions