ShareConf 2012

Christian Ahrenkiel and I presented “Toolkit für agile SharePoint-Entwicklung” at the ShareConf 2012 conference on 2012-06-20:

Agile Softwareentwicklung für SharePoint ist möglich, trifft aber auf einige technische Hindernisse. Das sind beispielsweise Änderungen an deklarativen Strukturen im bereits produktiven System oder mangels Transaktionen nicht voneinander isolierte Integrationtests. Wir zeigen, wie man diese Einschränkungen prinzipiell umgehen kann, und stellen einen Satz Bibliotheken vor, der einem diese Arbeit erleichtert.

Slides are available here: Agile SharePoint-Entwicklung – Malte_Clasen – ShareConf 2012 (PowerPoint 2010, 1.4 MB), and additionally on the ShareConf site. The content basically matches the Agile SharePoint Development series of blog postings.

SharePoint: Dependencies

Direct access to resources has a negative impact on testability. Take the SharePoint log as an example. It is hard to test automatically whether your code writes appropriate log entries. First you have to parse the log files, and second you have to find the right moment to do so as the log is written asynchronous. Access to external web services is a second source of confusion, since it is usually outside of the scope of a test environment and therefore not controlled and not reproducible. Instead of accessing these resources directly, you can define an interface for the resource and use it instead. Then you can use stubs or mocks during tests.

But how do you know whether you run in the context of a test? You don’t have to. Avoid creating instances of collaborating resources inside your implementation. Let someone on the outside do this for you. 

The Microsoft Patterns & Practices recommend using the Service Locator pattern for this. A Service Locator is a class with static properties, where someone stores a resource and later someone else gets it. Outside the SharePoint world, this is well known as an anti pattern. First, the usage of resources is not transparent. You cannot see which resources a class needs without looking at the implementation. This yields surprising errors in tests when the implementation changes. If a reference to an additional resource is added, the test compiles just fine, but no one adds the respective implementation to the Service Locator and the test fails at runtime. Second, all resources have to be re-initialized before each test run, because you don’t know whether the previous tests changed something.

Outside of SharePoint, the most common solution is dependency injection. The most simple way is to pass all resources as arguments to the constructor. You could also inject resources to properties of the object, if you have no control over its construction. This way each class clearly states its dependencies and the external code is responsible for satisfying these. You usually use a dependency injection container such as Ninject. You register all kinds of resources with your container, and the container will resolve the dependency chains at runtime. For automated tests you can also use a combination of AutoFixture and Moq to resolve all dependencies using mock objects.

SharePoint does not support dependency injection by default. Controls, Pages and all other framework objects are created somewhere inside SharePoint with no way to inject additional parameters into the constructor. The same issue appears in ASP.NET, so you can have a look at the solutions there. Ninject.Web provides base classes for property based dependency injection. You can do the same for SharePoint base classes, which call Inject(this) in their constructor.

We developed and implemented the dependency injection helper classes at adesso. We might publish the implementation, be it open or closed source, but this is still undecided. If you are interested in this, please leave a comment. I am not the one who decides, but we are actively seeking opinions on this, so you will actually influence the outcome.

SharePoint: Isolating Test Code

The Visual Studio templates for SharePoint projects default to GAC deployment. This means that all the code you write is going to be installed to the Global Assembly Cache (GAC). At first sight this seems pretty useful. No matter from which application you want to access your assemblies, they will be found automatically. SharePoint runs your code in different contexts, from IIS web applications to timer jobs, so this has actual value. But the GAC is no silver bullet, and you will notice that when you start writing tests. .NET prefers to load assemblies from the GAC, no matter what. If you deploy your class library to the GAC in your WSP, then change the source code and run the tests, .NET will load the previous version from the GAC, even if you updated the assembly your test is linked to. This can happen in more or less obvious ways. If you add a new class method, you will get a runtime linker error. It might not be clear that the outdated version in the GAC is the cause, but at least it is out of question that something went wrong. If you only changed the implementation, this can lead to headaches. You can step through your code in the debugger, but it behaves not as stated there. You recompile, and on the next run it still does things you thought you fixed a few minutes ago.

You have four alternatives to deal with the situation. First, you can always retract your WSPs before running the tests. This is annoying, and it fails when you need it most: Given a tricky bug in your business logic, you usually think about nothing else. This is when you forget to retract your WSPs, which in turn leads to strange behavior, which leads to even more quirks in your mental model of the business logic.

The second solution is to use assembly versioning. If you link to a specific version of your assembly, your outdated version in the GAC will be ignored. This way has the same drawback as the previous one: You will forget it. And even if you have enough discipline to update the assembly version whenever you change your code, you will run into conflicts when your colleagues work on the same assembly. As soon as you check in your code into version control, you have a conflict. It is easy to resolve, but it is annoying.

The third way is to install your class library to the GAC whenever you update it. This works on your local developer machine, but as soon as you start building different releases on a continuous integration machine, you will get conflicts when the different versions overwrite each other in the GAC. Additionally you have to deal with the insufficient robustness of gacutil.exe from the Windows SDK. When you call it too often in a row, it will start throwing errors about insufficient rights. Adding pauses can resolve this, but pauses are what developers hate the most during test-driven development.

So basically you have to find a way to avoid the GAC at all, the fourth alternative. The first step it to separate your code into a SharePoint interface and the actual program logic. The SharePoint interface should be as minimalistic as possible, it should only delegate the calls to the testable program logic. This logic is compiled as a separate class library. Now the SharePoint interface has to be able to find the logic. You cannot use the GAC, since you would run into the previously described problems. A common solution for stand alone applications is to integrate the assembly using ILMerge. This enables separate tests of the logic, while only a single assembly is going to be deployed. This works fine for a single closed program. It breaks down when multiple SharePoint solutions refer to the same assemblies. When a class library is integrated into multiple assemblies, .NET treats the code as separate copies. Therefore all types are multiplied. Accordingly all static variables are multiplied. This confuses even experienced developers.

Now we know that we cannot put the program logic in the GAC, and we cannot integrate it into the SharePoint interface assemblies. Looking at the project settings in Visual Studio, you see that there is a second deployment target, the bin folder of the web application. This has implications for code security. All assemblies in the GAC run with full trust by default. All assemblies in the bin folder are subject to the trust level specified in the web.config. This defaults to wss_medium. This might be sufficient, but depending on your code, you could have to elevate the rights for your assembly. Call the admins of the SharePoint farm your code is going to be deployed to and find an acceptable trust level and CAS policy. On your local machine you can also set the trust level to Full to get the same rights you would have in the GAC.

SharePoint finds assemblies in the bin folder automatically for all code running in the context of the web interface, for example WebParts. But it won’t take long until you notice that it doesn’t look into the bin folder for feature event receivers when activating features in the Visual Studio F5 deployment. The vssphost4.exe simply does not know about the bin folder. It’s the same for all the other SharePoint related non-web processes, such as timer jobs. The solution is to tell SharePoint about the bin folder. When .NET is unable to find an assembly, the event AssemblyResolve in System.AppDomain is fired. You can add a hook and try to load the assembly from the bin folder:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.SharePoint.Administration;

public static class AssemblyResolver
{
  public static void RegisterResolver(SPWebApplication webApplication)
  {    RegisterResolver(webApplication.IisSettings[SPUrlZone.Default].Path.ToString());
  }

  public static void RegisterResolver(string localWebApplicationPath)
  {    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args) { return AssemblyResolve(args, localWebApplicationPath); };
  }

  private static Assembly AssemblyResolve(ResolveEventArgs args, string localWebApplicationPath)
  {
    var name = new AssemblyName(args.Name);
    var files = System.IO.Directory.GetFiles(localWebApplicationPath + "/bin");
    return (from file in files 
        where System.IO.Path.GetFileNameWithoutExtension(file) == name.Name 
        select Assembly.LoadFrom(file))
        .FirstOrDefault(assembly => assembly.GetName().FullName == name.FullName);
  }
}

The only thing you need is a reference to the respective web application. In feature event receivers, you can get it via the feature parent object. In item event receivers, you can get it via the parent list of the item and its parent web.

You have to add the assembly resolve logic to the GAC. And you have to add the hook before .NET tries to invoke a function with a reference to a type in the bin folder. This is important since .NET ensures that all types are available before the function is entered, not when the actual line of code is reached. Using proxy classes for event receivers and similar SharePoint classes is a good way to hide all of this from developers.

We developed and implemented the proxy classes at adesso. We might publish the implementation, be it open or closed source, but this is still undecided. If you are interested in this, please leave a comment. I am not the one who decides, but we are actively seeking opinions on this, so you will actually influence the outcome.