Unit testing - Run unit tests without running Rhino.exe

Hi,
I have a C# solution that contains:

  • 1 Rhino plugin project
  • 1 class library project
  • 1 unit test project

I would like to perform unit tests on my class library implementation that contains references to RhinoCommon.dll such as Vector3d and Mesh. When I tried to run the unit tests, I encountered error: “System.IO.FileNotFoundException: Could not load file or assembly ‘RhinoCommon, Version=5.1.30000.16, Culture=neutral, PublicKeyToken=552281e97c755530’ or one of its dependencies. The system cannot find the file specified.”

I found some discussion about issues of running unit tests without running Rhino.exe due to dependencies of RhinoCommon.dll on Rhino.exe. But most of the discussions happened a few years ago.

I would like to check if such dependencies still valid and is there any solution to this issue?

Thank you.

PS: the version of RhinoCommon that I am currently using is 5.1

I have just put together an example repo of how this can be done using the latest WIP 7 release:

However if you are stuck with v5 you could try the steps described here:

Another option would be to try and run your tests from within Rhino using NUnit. See example repo here:

1 Like

Regarding the assembly not found issue you try the assembly resolve approach I’ve used here:

Look for the line AppDomain.CurrentDomain.AssemblyResolve += ResolveRhinoCommon

Thank you very much for the swift response.
I will try out the v5 steps.
As I planned to run the unit tests during the CI build, running the tests from within Rhino is not an option.

I had followed the steps in post. I no longer encounter error: “System.IO.FileNotFoundException: Could not load file or assembly ‘RhinoCommon, Version=5.1.30000.16, Culture=neutral, PublicKeyToken=552281e97c755530’ or one of its dependencies. The system cannot find the file specified.”

GeometryTests.cs (1.8 KB)

Unit test: CheckVector passed
However, unit test CheckBooleanUnion does not return. I had to manually kill the vstest.executionengine.x86.exe process in the end.

OK, first off CheckVector is probably not calling though to the native rhino DLL. As you are simply initialising a CLR (.NET) type and then checking its value. So I doubt that is fair test. I suggest you call Unitize() on your vector as that references the native stuff. See source here:

Let me know how that goes and then we can revisit the CheckBooleanUnion issue.

I experienced the same issue after I added a line in CheckVector:

v.Unitize();

Below are some information that I gathered from the Dump:

|Exception Code:|0xC0000005|
|Exception Information:|The thread tried to read from or write to a virtual address for which it does not have the appropriate access.|

I’ve just tried to run a basic test against Rhino 5 and I can’t get x86 working at all. I can get the 64 bit version to run intermittently, but I’m also getting memory access violations. It used to work in the past, but who knows what has changed since then. Windows updates, VS updates, MS Test updates, Rhino Updates etc.

So in summary I would suggest you abandon your CI integration for Rhino 5 as it is too fragile.Your time is probably better spent elsewhere. I understand just how much time this stuff can soak up. I learnt recently that even McNeel themselves don’t run unit tests as part of their CI. Instead they run the tests manually every now and again.

It is worth noting that you can probably run 95% of your v5 code against they latest WIP v7 without any changes at all. That is probably your best bet if you really need CI integration. To get access to v7 you just need a single v6 license. https://www.rhino3d.com/download/rhino/wip

Thank you very much for your time in verifying my findings and also your suggestion.
With all this information, I will be able to make a better conclusion and decision.:smiley:

Apologies for reviving an old topic, but I thought I’d post my current method for future searches. In my case all the functionality that needs to be tested is available in Rhino3dmIO.

I have two projects:

  • RhinoPluginProject
    • [NuGet] RhinoCommon
    • MyRhinoPlugin.cs
    • MyFunctionality.cs
  • TestProject
    • [NuGet] Rhino3dmIO
    • [Link] MyFunctionality.cs

The plugin project references the NuGet dlls for Rhino and Grasshopper and is otherwise an entirely normal Rhino plugin.

The test project does not reference the plugin project or RhinoCommon, but instead has the relevant classes included as file links (Add as Link in VS), and references Rhino3dmIO via NuGet.

Where there are any missing features I write a simple shim in the test project that provides a value to use for testing. For example, a shim for Rhino.RhinoDoc.ActiveDoc.ModelUnitSystem might look like:

namespace Rhino
{
    public class RhinoDoc
    {
        private static RhinoDoc _activeDoc;
        public static RhinoDoc ActiveDoc
        {
            get
            {
                if (_activeDoc == null)
                {
                    _activeDoc = new RhinoDoc();
                }
                return _activeDoc;
            }
        }

        public UnitSystem ModelUnitSystem => UnitSystem.Millimeters;
    }
}

Some things to note:

  • Rhino3dmIO targets Rhino 6, but this is good enough to test for Rhino 5 as well in my case as I’m not using any 6-specific features.
  • I haven’t yet tested this with a CI pipeline, but also don’t see any reason why this shouldn’t work.
  • There are of course many scenarios where the overhead of writing the shims would be far too great, in which case executing the tests in the plugin is likely a better idea.
1 Like