Extending Shadow Copy to Test Projects with Dependencies

I have an nunit test project that depends on various libraries.  To keep build times short, the CopyLocal setting for my assembly references is set to false.  This means my output directory is nice and simple: it only contains the dll and symbols for my test assembly.  This presents a problem when I use the Resharper test runner, however.  Nunit obviously can't run the tests because it cannot locate the depedencies.

I was thinking Resharper might be able to help me out with this.  I don't want to set CopyLocal to true, because I value the shorter build time.  But could Resharper's "shadow copy" feature be helpful here?  Could whatever process Resharper is using to copy my assembly to a temp directory be extended to also copy the dependency dlls?  I don't know whether Resharper is doing this shadow copy stuff on its own or using Microsoft's version of shadow copy; if the latter, then maybe this isn't possible.

Or, is there another way people have accomplished using the Resharper test runner on projects without CopyLocal dependencies?


1 comment
Comment actions Permalink

You'll be better off to set copy local for your dependencies to be true for your test project. MSBuild will do the copying, but it will only copy them once - if the files already exist, they don't get copied, so that will help keep your build time low. Also, if the assemblies are referenced with a valid hint path in the csproj file, MSBuild will be able to go straight to the file - if there's no hint path, it searches many locations, for each reference. This will adversely affect build time.

The reason I'm saying to do this is that ReSharper's test runner needs those files, so they need to be copied anyway. It would be better to let msbuild do it (and use a tried and tested mechanism) than to rebuild something that already exists. Also, the shadow copy that ReSharper's uses is the shadow copy that .net provides as part of AppDomain creation - and .net requires the files to be in place for the shadow copy to work.

Surprisingly, and contrary to many posts on the internet, my experience is that disabling copy local isn't the answer to faster build times, because you end up with the situation you describe - a folder containing an assembly that won't run. If all of your dependencies are in the GAC, this isn't a problem, but this isn't the usual scenario, and so will most likely fail. What you should do is build each project to a common directory, with copy local set to TRUE. The time is usually lost by copying dependencies between sub-projects. E.g. if I have a solution with 10 projects, and several dependencies between projects, then I will see some assemblies and their dependencies copied around about 10 times. But if they get built to a common directory, they only ever get copied once - and if the dependency hasn't changed it doesn't get copied again. I've had great success doing this with a solution that contained approx 60 projects. If you have a project that is an "entry point" (e.g. web services, executable, test project), either run it directly from the common directory, or build that project to its own location, again with copy local true. The amount of copying around has already been greatly reduced, so copying for one project (when most of the dependencies probably won't change) won't hurt too much.


Please sign in to leave a comment.