Assembly references and dependencies


I’m currently working on a largish solution in VS2008 – maybe fifteen or twenty projects. We’re using Smart Client Software Factory (SCSF) and TDD for all of our code where possible. One of the things that SCSF gives you is the ability to create a unit test project for every business module that you create for free. This is nice, except that having all those extra projects slows down build time and almost doubles the number of assemblies that you have. Plus, it makes it harder to share code across your unit test projects.

So I made the decision a few days ago to make a new unit test project which would contain all our unit tests, divided by folders and namespaces for the different areas that we were testing. This has turned out to be a Good Thing, as we now can easily e.g. make base unit test classes to do a lot of the grunt work of our unit tests – so it aids readability when maintaining the tests, and also cuts down on the boilerplate code that you need to write.

Anyway, you might be wondering “what does this have to do with assembly references”? Well, the problem I noticed shortly after doing this was that the build time just for running unit tests was pretty long – maybe twenty seconds. Bear in mind that we might change unit tests every minute or so – so effectively a third of our time is being wasted on rebuilds of the solution. I couldn’t understand why this was until I looked at the build output window – EVERY referenced project gets rebuilt whenever we modify a unit test!

Understand that our unit test assembly references maybe ten (or more) different assemblies containing testable code – every time we need to change a single unit test, it rebuilds all ten of them – even those that have no dependencies on them. None of them have changed at all – just the unit test project. And there’s nothing referencing my unit test assembly at all.

I can’t understand why this is. On my home PC, doing this doesn’t do the same thing – if I create a class library and then a unit test project, and then modify some of the unit testing code (but NOT the class library itself), I see the following in VS’s output window:

 

—— Build started: Project: ClassLibrary1, Configuration: Debug Any CPU ——
ClassLibrary1 -> C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\ClassLibrary1\bin\Debug\ClassLibrary1.dll
—— Build started: Project: TestProject1, Configuration: Debug Any CPU ——
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\ClassLibrary1\bin\Debug\ClassLibrary1.dll" /reference:"C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /debug+ /debug:full /filealign:512 /optimize- /out:obj\Debug\TestProject1.dll /target:library Properties\AssemblyInfo.cs UnitTest1.cs

Compile complete — 0 errors, 0 warnings
TestProject1 -> C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\TestProject1\bin\Debug\TestProject1.dll
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========

 

Notice how TestProject1 does a recompile (with the call to csc.exe), whereas ClassLibrary1 does not – because VS knows that ClassLibrary1 has not changed.

If I then do indeed modify something in ClassLibrary1 but not TestProject1, and re-run my unit tests, I get the following:

—— Build started: Project: ClassLibrary1, Configuration: Debug Any CPU ——
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll" /debug+ /debug:full /filealign:512 /optimize- /out:obj\Debug\ClassLibrary1.dll /target:library Class1.cs Properties\AssemblyInfo.cs

Compile complete — 0 errors, 0 warnings
ClassLibrary1 -> C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\ClassLibrary1\bin\Debug\ClassLibrary1.dll
—— Build started: Project: TestProject1, Configuration: Debug Any CPU ——
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\ClassLibrary1\bin\Debug\ClassLibrary1.dll" /reference:"C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /debug+ /debug:full /filealign:512 /optimize- /out:obj\Debug\TestProject1.dll /target:library Properties\AssemblyInfo.cs UnitTest1.cs

Compile complete — 0 errors, 0 warnings
TestProject1 -> C:\Users\Isaac\Documents\Visual Studio 2008\Projects\ClassLibrary2\TestProject1\bin\Debug\TestProject1.dll
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========

 

This time, both projects have been recompiled – ClassLibrary1 because it was changed since the last build, and TestProject1 because it’s dependant on ClassLibrary1. This makes perfect sense to me.

If I add another class library into the mix, VS continues to behave properly, only doing rebuilds where necessary.

Yet on my work solution, this is not the case. EVERY assembly gets rebuilt EVERY time. I cannot find any rhyme or reason for this though! Does anyone know how VS determines whether an assembly is “dirty” (and therefore needs to be rebuilt) – my guess is that something is interfering with that and causing it to rebuild every assembly regardless….

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s