Tuesday, April 07, 2009

MbUnit + AutoCAD = Unit testing for CAD Plugins

If you follow my blog, you know that I develop CAD plug-ins in both .NET and C++. And in various posts of mine I have written about the difficulty of writing unit tests for these CAD plug-ins. The following are some of my more relevant posts regarding this topic.

My usual solution was to avoid unit testing these CAD plugins and simply write integrated tests for them. The last post mentioned above (Writing CEEFIT class like a regular C++ class) specifically shows a sample CEEFIT (Framework for Integrated Test for C/C++) class that enables integrated testing using SWX (I will post the complete workspace to do this soon).

But imagine my surprise when I read the following post about the release of MbUnit v3.0.5 - http://weblogs.asp.net/astopford/archive/2009/04/02/mbunit-3-rtm.aspx. The below text is an excerpt from that post (bold and italics are my addition):
Gallio provides MbUnit with the runner infrastructure and the list of supported runners is amazing, like MbUnit v2 you can still run MbUnit v3 in MSBuild, NAnt, TD.Net, CruiseControl, commandline (much more ehanched in v3) and GUI (also vastly enhanced in v3) but now tools such as TeamCity, VSTS, Resharper, Powershell, NCover, TypeMock and even AutoCAD.
That last word really caught my attention. What is this? Unit test support for CAD system plug-ins? That is so awesome it is beyond belief. A Google search for "AutoCAD MbUnit" gave more information via http://blog.bits-in-motion.com/2008/11/announcing-gallio-and-mbunit-v305.html. An excerpt:

AutoCAD Integration

Mike Sandberg has added support for testing AutoCAD plugins.
It turns out that AutoCAD has a managed extensibility model so you can create your own plugins using .Net and the ObjectARX toolkit.  Unfortunately it is somewhat difficult to write unit tests for plugins becuase they must run within the main UI thread of AutoCAD.
The AutoCAD integration for Gallio works by loading a shim into the AutoCAD application from which it can launch tests.  To enable this integration, specify the "AutoCAD" runner type to the Echo, Icarus, MSBuild, NAnt or PowerShell runners.
For example:

    Gallio.Echo.exe MyTestAssembly.dll /r:AutoCAD [other options...]

AutoCAD integration is not yet available from within the IDE.  We will be working to improve this use case in the future.
OK. This definitely is promising. The post provides usage scenario, and although low on details on how this is achieved beyond saying "loading a shim", it is exactly what we CAD developers need.

To learn more on how MbUnit developers solved this problem, I turned to the source code available at http://mb-unit.googlecode.com/svn/trunk/v3/src/Extensions/AutoCAD. From first glances it looks as though the shim can connect or load (via the "acad.exe" file) AutoCAD. The shim finds the path to "acad.exe" via the registry key
"HKEY_CURRENT_USER\Software\Autodesk\DWGCommon\shellex\Apps\{F29F85E0-4FF9-1068-AB91-08002B27B3D9}:AutoCAD". 
It then determines if your plugin is loaded and if yes, sends commands to it using a TestDriver (AcadTestDriver).

What I found even more intriguing was the description of the problem that MbUnit developers intended to solve i.e. "difficulty of running unit tests as they run in the main UI thread of AutoCAD ". As I have contended, this is an universal problem for CAD developers. Replace AutoCAD with SolidWorks and the posts that I list above were intended to solve this very problem, although with a hack of a solution, but still following the same lines of thought. The CEEFIT workspace that I work with, loads SolidWorks in the background and using COM, connects to the running instance and then executes SWX-API-based tests. I let CEEFIT be the TestDriver and validate my output. The MbUnit framework has packaged idea this in beautiful .NET code.

This brings up the possibility that since SolidWorks plugins can also be .NET based, would replacing AutoCAD connection commands with SolidWorks connection commands in MbUnit's framework, allow loading the shim into SolidWorks and run unit tests against SolidWorks. I will be exploring this possiblity in the coming weeks/months, as time permits.

Do you develop AutoCAD plugins? Is this new functionality of MbUnit useful to you? Comments welcome.