Skip to content
Matthew Adams By Matthew Adams Co-Founder
SpecFlow 2.0, NUnit3, Visual Studio and TeamCity

We have recently upgraded our build environment to use SpecFlow 2.0, and NUnit3.

NUnit3 is supported by the latest build of TeamCity, and there is an NUnit3 Test Adapter for Visual Studio, but there are a few gotchas.

The first is to do with the base directory set by the NUnit Test Adapter in Visual Studio.

Unlike the previous version of the NUnit Runner, the current directory is set to the runner's installation directory, rather than the directory in which the tests are found.

Fortunately, NUnit3 provides TestContext.CurrentContext.TestDirectory which helps a lot.

We've created a SpecFlow hook to change the current directory to the test directory for features that need it (e.g. when loading external support files)

[Binding]    
public class NUnit3Hooks    
{        
  [BeforeFeature("workingdirectory_feature")]        
  public static void ChangeWorkingDirectory()        
  {            
    FeatureContext.Current.Add("NUnit3Hooks.OldWorkingDirectory", Directory.GetCurrentDirectory());
    Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory);
  }
  [AfterFeature("workingdirectory_feature")]
  public static void RestoreWorkingDirectory()  
  {                     
    Directory.SetCurrentDirectory(FeatureContext.Current.Get("NUnit3Hooks.OldWorkingDirectory"));
  }
}

The second problem comes with executing the tests under TeamCity.

TC builds an NUnit project file to execute multiple test assemblies it discovers in your build. This is great - unless you are, for example, dynamically loading assemblies from the application base directory, as TC sets it to the root of the source checkout tree, rather than the directory executing the test assembly. (This is by design, and perfectly reasonable given the way NUnit executes multiple-assembly tests using the project file.)

However, it is no good if you want the individual test assemblies to be isolated, and loaded into their own AppDomain whose base directory is the test assembly location.

Fortunately, you can control how TC drives NUnit, by adding a build configuration parameter "nunit_use_project_file".

Edit your build configuration, select "Parameters" and add an additional parameter as in the image below.

BuildConfigSettingsParameters

If you set this to 'false' then TC doesn't build a project file, but passes the assemblies to NUnit on the command line. This causes NUnit to run them each in its own AppDomain, with the BaseDirectory set correctly.

Matthew Adams

Co-Founder

Matthew Adams

Matthew was CTO of a venture-backed technology start-up in the UK & US for 10 years, and is now the co-founder of endjin, which provides technology strategy, experience and development services to its customers who are seeking to take advantage of Microsoft Azure and the Cloud.