diff --git a/README.md b/README.md
index 9b7c2ca..72d128f 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# RhinoCommon Unit Testing
## Intro
-Example of unit testing RhinoCommon from within the Visual Studio test runner on windows.
+Examples of unit testing RhinoCommon and Grasshopper3d.
## Prerequisites
Rhino 7
@@ -11,23 +11,34 @@ Visual Studio 2019
https://www.visualstudio.com/downloads/
## Test Framework
-This project provides examples for XUnit and MS Test,
-but the principles would be easily transferable to other frameworks if needs.
+This project provides three example projects.
+ - One using the MsTest Framework `RhinoPlugin.Tests`
+ - A second one using Xunit `RhinoPlugin.Tests.Xunit`
+ - And a thrid one using the old .csproj format without PackageReference Migration where Grasshopper3d libraries are loaded directly by Rhino.Inside `RhinoPlugin.Tests.GHAutoLoad`
+
+but the principles would be easily transferable to other frameworks if needed.
## How to Run
- Build the solution
- Test should appear in Visual Studio Test Explorer
- Set test enviroment to x64
`Test > Test Settings > Default Processor Architecture > x64`
-- Click `Run All` to run the tests
+- Click `Run All` to run the tests.
+- Some times you may need to run each project individualy as the testhost tends to get stuck.
## Further Reading
-For more info on using Rhino in a headless environment see the Rhino Compute project:
-https://github.com/mcneel/compute.rhino3d
+For more info on using Rhino in a headless environment or inside other applications please see the projects below:
+- https://github.com/mcneel/compute.rhino3d
+- https://github.com/mcneel/rhino.inside
+
+
+## Known issues
+Using the new *.csproj* format, the headless version of Rhino fails to load the GH libraries. To tackle this we are loading the library manually to the test context by resolving the specific assembly.
+
+If you are using the old .csproj format and with a packages.config for the references then GH is loading automatically.
## Troubleshooting
- Note that when Rhino is in headless mode there is no document defined.
The static property `RhinoDoc.ActiveDoc` will thus be null which may trip up your plugin code.
-- If you have any problems getting this to work or you have a more complex use case,
-then please get in touch via the issue tracker.
+- If you have any problems getting this to work or you have a more complex use case, please get in touch via the issue tracker.
\ No newline at end of file
diff --git a/RhinoCommonUnitTesting.sln b/RhinoCommonUnitTesting.sln
index c11353a..9a16064 100644
--- a/RhinoCommonUnitTesting.sln
+++ b/RhinoCommonUnitTesting.sln
@@ -12,6 +12,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RhinoPlugin.Tests.Xunit", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RhinoPlugin.Tests", "Src\RhinoPlugin.Tests\RhinoPlugin.Tests.csproj", "{5F877072-8EA6-4CE3-9A6B-6CF201E3CB73}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RhinoPlugin.Tests.GHAutoLoad", "Src\RhinoPlugin.Tests.GHAutoLoad\RhinoPlugin.Tests.GHAutoLoad.csproj", "{ACE64814-311F-4B9B-9DFE-31AE9A9030E3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -26,6 +28,10 @@ Global
{5F877072-8EA6-4CE3-9A6B-6CF201E3CB73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F877072-8EA6-4CE3-9A6B-6CF201E3CB73}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F877072-8EA6-4CE3-9A6B-6CF201E3CB73}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ACE64814-311F-4B9B-9DFE-31AE9A9030E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ACE64814-311F-4B9B-9DFE-31AE9A9030E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ACE64814-311F-4B9B-9DFE-31AE9A9030E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ACE64814-311F-4B9B-9DFE-31AE9A9030E3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Src/RhinoPlugin.Tests.GHAutoLoad/Properties/AssemblyInfo.cs b/Src/RhinoPlugin.Tests.GHAutoLoad/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a63e55a
--- /dev/null
+++ b/Src/RhinoPlugin.Tests.GHAutoLoad/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RhinoPlugin.Tests.RHInside")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RhinoPlugin.Tests.RHInside")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ace64814-311f-4b9b-9dfe-31ae9a9030e3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Src/RhinoPlugin.Tests.GHAutoLoad/RhinoPlugin.Tests.GHAutoLoad.csproj b/Src/RhinoPlugin.Tests.GHAutoLoad/RhinoPlugin.Tests.GHAutoLoad.csproj
new file mode 100644
index 0000000..10fd04d
--- /dev/null
+++ b/Src/RhinoPlugin.Tests.GHAutoLoad/RhinoPlugin.Tests.GHAutoLoad.csproj
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+ Debug
+ AnyCPU
+ {ACE64814-311F-4B9B-9DFE-31AE9A9030E3}
+ Library
+ Properties
+ RhinoPlugin.Tests.RHInside
+ RhinoPlugin.Tests.RHInside
+ v4.8
+ 512
+ true
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\packages\RhinoCommon.7.0.20314.3001\lib\net45\Eto.dll
+
+
+ ..\..\packages\RhinoWindows.7.0.20314.3001\lib\net45\Eto.Wpf.dll
+
+
+ ..\..\packages\Grasshopper.7.0.20314.3001\lib\net45\GH_IO.dll
+
+
+ ..\..\packages\Grasshopper.7.0.20314.3001\lib\net45\Grasshopper.dll
+
+
+ ..\..\packages\RhinoCommon.7.0.20314.3001\lib\net45\Rhino.UI.dll
+
+
+ ..\..\packages\RhinoCommon.7.0.20314.3001\lib\net45\RhinoCommon.dll
+
+
+ ..\..\packages\Rhino.Inside.7.0.0\lib\net48\RhinoInside.dll
+
+
+ ..\..\packages\RhinoWindows.7.0.20314.3001\lib\net45\RhinoWindows.dll
+
+
+
+
+
+
+
+
+
+
+ ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll
+ True
+
+
+ ..\..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll
+
+
+ ..\..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll
+
+
+ ..\..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Src/RhinoPlugin.Tests.GHAutoLoad/XunitExampleTestsRI.cs b/Src/RhinoPlugin.Tests.GHAutoLoad/XunitExampleTestsRI.cs
new file mode 100644
index 0000000..121c959
--- /dev/null
+++ b/Src/RhinoPlugin.Tests.GHAutoLoad/XunitExampleTestsRI.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Rhino.Geometry;
+using Grasshopper.Kernel.Types;
+
+using Xunit;
+
+
+namespace RhinoPlugin.Tests.GHAutoLoad
+{
+ ///
+ /// XUnit tests
+ ///
+ [Collection("RhinoTestingCollection")]
+ public class XunitExampleTestsRI
+ {
+ XunitTestFixtureRI _fixture;
+
+ public XunitExampleTestsRI(XunitTestFixtureRI fixture)
+ {
+ fixture = _fixture;
+ }
+
+ [Fact]
+ public void Brep_Translation()
+ {
+
+ // Arrange
+ var bb = new BoundingBox(new Point3d(0, 0, 0), new Point3d(100, 100, 100));
+ var brep = bb.ToBrep();
+ var t = Transform.Translation(new Vector3d(30, 40, 50));
+
+ // Act
+ brep.Transform(t);
+
+ // Assert
+ Assert.Equal(brep.GetBoundingBox(true).Center, new Point3d(80, 90, 100));
+
+ }
+
+ ///
+ /// Xunit Test to Intersect sphere with a plane to generate a circle
+ ///
+ [Fact]
+ public void Brep_Intersection()
+ {
+ // Arrange
+ var radius = 4.0;
+ var brep = Brep.CreateFromSphere(new Sphere(new Point3d(), radius));
+ var cuttingPlane = Plane.WorldXY;
+
+ // Act
+ Rhino.Geometry.Intersect.Intersection.BrepPlane(brep, cuttingPlane, 0.001, out var curves, out var points);
+
+ // Assert
+ Assert.Single(curves);
+ Assert.Equal(2 * Math.PI * radius, curves[0].GetLength());
+ }
+
+ ///
+ /// Xunit Test to ensure Centroid of GH_Box outputs a GH_Point
+ ///
+ [Fact]
+ public void GHBox_Centroid_ReturnsGHPoint()
+ {
+ // Arrange
+ var myBox = new GH_Box(new Box());
+
+ // Act
+ var result = myBox.Boundingbox.Center;
+
+ // Assert
+ Assert.IsType(result);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Src/RhinoPlugin.Tests.GHAutoLoad/XunitTestFixtureRI.cs b/Src/RhinoPlugin.Tests.GHAutoLoad/XunitTestFixtureRI.cs
new file mode 100644
index 0000000..6f63caa
--- /dev/null
+++ b/Src/RhinoPlugin.Tests.GHAutoLoad/XunitTestFixtureRI.cs
@@ -0,0 +1,74 @@
+using Microsoft.Win32;
+using System;
+using System.IO;
+using System.Reflection;
+using Xunit;
+
+namespace RhinoPlugin.Tests.GHAutoLoad
+{
+
+ ///
+ /// Shared test context across unit tests that loads rhinocommon.dll and grasshopper.dll
+ ///
+ public class XunitTestFixtureRI : IDisposable
+ {
+
+ private Rhino.Runtime.InProcess.RhinoCore _rhinoCore;
+
+ ///
+ /// Empty Constuctor
+ ///
+ public XunitTestFixtureRI()
+ {
+ // Use the latest version of RH7 installed in your system
+ RhinoInside.Resolver.UseLatest = true;
+
+ // Make sure we are running the tests as 64x
+ Assert.True(Environment.Is64BitProcess, "Tests must be run as x64");
+
+ //Initialize Rhino.Inside
+ RhinoInside.Resolver.Initialize();
+
+ // Set path to rhino system directory
+ string envPath = Environment.GetEnvironmentVariable("path");
+ Environment.SetEnvironmentVariable("path", envPath + ";" + RhinoInside.Resolver.RhinoSystemDirectory);
+
+ // Start Rhino and load all libraries
+ StartRhino();
+
+ }
+
+ ///
+ /// Starting Rhino - loading the relevant libraries
+ ///
+ [STAThread]
+ public void StartRhino()
+ {
+ _rhinoCore = new Rhino.Runtime.InProcess.RhinoCore(null, Rhino.Runtime.InProcess.WindowStyle.NoWindow);
+ }
+
+ ///
+ /// Disposing the context after running all the tests
+ ///
+ public void Dispose()
+ {
+ // do nothing or...
+ _rhinoCore?.Dispose();
+ _rhinoCore = null;
+ }
+ }
+
+
+ ///
+ /// Collection Fixture - shared context across test classes
+ ///
+ [CollectionDefinition("RhinoTestingCollection")]
+ public class RhinoCollection : ICollectionFixture
+ {
+ // This class has no code, and is never created. Its purpose is simply
+ // to be the place to apply [CollectionDefinition] and all the
+ // ICollectionFixture<> interfaces.
+ }
+
+}
+
diff --git a/Src/RhinoPlugin.Tests.GHAutoLoad/packages.config b/Src/RhinoPlugin.Tests.GHAutoLoad/packages.config
new file mode 100644
index 0000000..46ff6d7
--- /dev/null
+++ b/Src/RhinoPlugin.Tests.GHAutoLoad/packages.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Src/RhinoPlugin.Tests.Xunit/XunitTestFixture.cs b/Src/RhinoPlugin.Tests.Xunit/XunitTestFixture.cs
index 3f7a7af..ca2928d 100644
--- a/Src/RhinoPlugin.Tests.Xunit/XunitTestFixture.cs
+++ b/Src/RhinoPlugin.Tests.Xunit/XunitTestFixture.cs
@@ -60,19 +60,29 @@ public void StartRhino()
}
///
- /// Add Grasshopper.dll to the current Appdomain
+ /// Add Grasshopper.dll and GH_IO to the current Appdomain
///
private Assembly ResolveGrasshopper(object sender, ResolveEventArgs args)
{
var name = args.Name;
- if (!name.StartsWith("Grasshopper"))
+ if (name.StartsWith("Grasshopper"))
{
- return null;
+ var path = Path.Combine(Path.GetFullPath(Path.Combine(rhinoDir, @"..\")), "Plug-ins\\Grasshopper\\Grasshopper.dll");
+ return Assembly.LoadFrom(path);
}
- var path = Path.Combine(Path.GetFullPath(Path.Combine(rhinoDir, @"..\")), "Plug-ins\\Grasshopper\\Grasshopper.dll");
- return Assembly.LoadFrom(path);
+ if (name.StartsWith("GH_IO"))
+ {
+ var path = Path.Combine(Path.GetFullPath(Path.Combine(rhinoDir, @"..\")), "Plug-ins\\Grasshopper\\GH_IO.dll");
+ return Assembly.LoadFrom(path);
+ }
+
+ else
+ {
+ return null;
+ }
+
}
///