Closed nicolashahn closed 3 years ago
I didn't have tests in mind at all, so as we can see they are probably not supported ¯_(ツ)_/¯.
That said, I don't see why they shouldn't work (though I don't know/remember how the unit test frameworks works either). The most important thing is whether the DllManipulatorScript
is instantiated in the scene (I guess there is some scene?) before the test method runs, just like in play mode. Can you confirm that?
If you cannot ensure that by the UI as you can in the editor, you can probably use the setup functionality of NUnit. Try adding a [Setup]
method which instantiates the DllManipulatorScript
script and maybe call it's Initialize
method.
Btw. if you do DllImport("__<plugin>")
then you're just using the native Unity's plugin handling (not this tool), so it won't be reloadable either way.
The most important thing is whether the DllManipulatorScript is instantiated in the scene (I guess there is some scene?) before the test method runs, just like in play mode. Can you confirm that?
Yes, I added a log inside DllManipulatorScript's Initialize()
function that appeared when I ran the test. Maybe this is getting called after the test method?
If you cannot ensure that by the UI as you can in the editor, you can probably use the setup functionality of NUnit. Try adding a [Setup] method which instantiates the DllManipulatorScript script and maybe call it's Initialize method.
I'm not sure what the import statement should be (using UnityNativeTool
or Plugins.UnityNativeTool
don't work). This is my project layout:
Btw. if you do DllImport("__
") then you're just using the native Unity's plugin handling (not this tool), so it won't be reloadable either way.
I'm aware, I copied the file after I had done the change just to make sure the test would pass at all.
Yes, I added a log inside DllManipulatorScript's Initialize() function that appeared when I ran the test. Maybe this is getting called after the test method?
Yup, that's important it's called before the test method, you should check that.
using
UnityNativeTool
orPlugins.UnityNativeTool
don't work
Hmm.. that should be UnityNativeTool
, but if you don't see that, then it probably means you don't target the tools assembly (mcpiroman.UnityNativeTool
). AFAIK there should be an option somewhere in Unity to specify them for tests.
Speaking of assemblies, that might be the issue here. If the test framework uses different assembly than the main one, Assembly-CSharp
, (and I'm pretty sure it does), than it is not considered by default and you need to add it in options (Only Assembly-CSharp(-Editor)
).
I'm not sure exactly what you mean by changing assemblies, however: I was able to add using UnityNativeTool
by changing PlayTestScript.asmdef:
{
"name": "PlayModeTests",
"optionalUnityReferences": [
"TestAssemblies"
],
"references": [
"mcpiroman.UnityNativeTool"
]
}
Now my PlayTestScript is:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.SceneManagement;
using UnityNativeTool;
public class PlayTestScript
{
[DllImport("RenderingPlugin")]
private static extern int TestFunction();
[SetUp]
public void Setup()
{
var script = new DllManipulatorScript();
script.Initialize();
Debug.Log("did DllManipulatorScript.Initialize() in test Setup()");
}
[Test]
public void PlayTestScriptSimplePasses()
{
Debug.Log("doing test");
Assert.AreEqual(42, TestFunction());
}
}
and when I run the test, the setup log shows up before the test's log, but I'm still seeing System.DllNotFoundException : RenderingPlugin
error on the line that calls TestFunction()
.
I'm not sure exactly what you mean by changing assemblies, however: I was able to add using UnityNativeTool by changing PlayTestScript.asmdef:
Well, I meant just that what you did there.
Secondly, you will need to add the test assembly to the list of mocked assemblies, because by default only Assembly-CSharp(-Editor)
is being considered. If you setup this from code, then you probably need to do something like
var script = new DllManipulatorScript();
script.Options.assemblyNames = new List() { "PlayModeTests" // or whatever the test assembly name is }
script.Initialize();
You may try to find the assembly name by something like AppDomain.Current.Assembly.Name
, sth like that, don't remember now. And if you find out the name and it works, please share it here so I can add it to defaults without checking myself.
Thanks for that code, it worked and now I can run the test. However, now it appears that Unity won't unlock the __RenderingPlugin.dll
file after the test has run and I need to restart Unity to be able to change the plugin, defeating the point of this tool :( any idea what's going on?
Thanks for all your help so far, by the way.
Oh yes, you'll need to unload the DLLs somehow, there is no 'stop' button after all. So I suggest you just use the teardown method (analogous to setup) and call DllManipulator.UnloadAll()
. Or DllManipulator.Reset()
if you don't use it anymore - you'll have to find out which is more correct for you, depending on how the tests work - remember DllManipulator
is static tho.
It looks like Unity still won't give up the file. Here's my setup and teardown:
[SetUp]
public void Setup()
{
SceneManager.LoadScene("TestScene", LoadSceneMode.Single);
var obj = new GameObject();
var script = obj.AddComponent<DllManipulatorScript>();
script.Options.assemblyNames = new List<string> { "PlayModeTests" };
script.Initialize();
}
[TearDown]
public void Teardown()
{
DllManipulator.UnloadAll();
SceneManager.UnloadSceneAsync("TestScene");
}
edit: Reset() does not work either
Oh, my bad! I had the Dll loading mode
set to "Preload" for the script settings. After I changed it to "Lazy" it's working as intended. Thank you again!
I'm using this successfully in play mode but when I run play mode tests in Unity Test Framework, I'm seeing a
System.DllNotFoundException
. When I replace theDllImport("<plugin>")
withDllImport("__<plugin>")
in the test file it works, but then I have to restart Unity to load a new version of the plugin. Is this something you can help with?Here's my test file if it helps: