Debugging a R# test runner is, thankfully, not an experience most people will have to go through.
Because ReSharper runs unit tests in a separate process, spun up on demand, you need to find some way to attach to this process.
The brute force approach is simply to throw an exception somewhere in your plugin, and then attach.
A better alternative is to launch VS in ReSharper.Internal mode (or “god mode”, as some like to refer to it) by supplying the /ReSharper.Internal argument to devenv.exe. (You can also enable a specific plugin by using /ReSharper.Plugin “MyPlugin.dll”, which spares some of the pain when trying to build a plugin that is in use).
This provides you with some extra options. The one you want is “Enable Debug (Internal)” which can be found in ReSharper->Options->Tools->Unit Testing:
Once this is enabled, when you run a test a dialog will appear:
Giving you time to attach to the test runner:
Most ReSharper information comes from code inspection and analysis, but not all details can be inferred from the source code alone. For example, code called by reflection (e.g. Activator.CreateInstance) looks like dead code to static analysis. R# offers a solution in the form of External Annotations, XML files supplying extra information.
If you use a test framework other than NUnit, e.g. MbUnit, you may find that your tests are marked as unused by R# even though they can be run. This can fixed by supplying some annotations, the XML needs to go in “%SystemDrive%\Program Files\JetBrains\ReSharper\[Build#]\Bin\ExternalAnnotations\[DllName]\[DllName].xml”. So for MbUnit, it would be ExternalAnnotations\MbUnit\MbUnit.xml. The file needs a list of types, associated with the appropriate R# attribute. The MeansImplicitUseAttribute:
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
states that any code tagged with the TestAttribute will not be considered unused. Other useful attributes are the AssertionMethodAttribute:
and the NotNullAttribute. An external annotation file is shipped with the more recent versions of MbUnit.
I recently had the dubious pleasure of downgrading a .net 3.5 project, with liberal use of extension methods, to .net 2.0. I was getting pretty bored of typing, when I stumbled across a new refactoring (for me at least):
Convert Extension Method to Plain Static
R# to the rescue, once again!