New Relic and Nancy

At DrDoctor we’ve been using Nancy as our web framework for quite sometime now. We’ve found it to have many advantages over ASP.Net MVC (we still have one legacy ASP.Net MVC site running) as well as excellent community support.

Recently we started using New Relic to monitor the performance of our web applications. However I was a bit disappointed when I was first looking at the data it collected and saw this

1-not-splitting-routes

New Relic grouped up all the different routes under the title of “NancyHttpRequestHandler”, I compared this to the list of Transactions that New Relic had picked up from our ASP.Net MVC application and there was a nice list of all the different routes that had been visited.

After a very quick Google search I came across the Nancy and New Relic page on the Nancy wiki and after following the instructions and redeploying our website New Relic started to list all the different Nancy routes

2-individual-routes

New Relic will also pick up any exceptions that are thrown and show these in the Errors section.

We’ve had New Relic capturing data performance data for about a month now and have already used it to make significant improvements to some of the key parts of our web apps.

Advertisements

Nancy and NCrunch – Playing nicely together…at last

If you haven’t tried NCrunch before then stop reading this and go download the trial and try it out, it will forever change your testing habits* – for the better.

NCrunch is the breakfast of champions

-KenR

At DrDoctor we use Nancy (rather than the typically used ASP.Net MVC Framework) the main reason is summed up by the overall goal of the framework:

The goal of the framework is to stay out of the way as much as possible and provide a super-duper-happy-path to all interactions.

One of the greatest things about Nancy vs ASP.Net MVC is that everything can be tested, and we have tests for pretty much all of our Modules (read Controllers) as well as our Views. NCrunch does some serious magic when it comes to running your test intelligently in parallel. Up until a few days ago I couldn’t figure out how to get my tests to work.

Testing Nancy Views

Testing Nancy Views is very easy, for demonstration purposes I created a new Nancy project from the standard ASP.Net and Razor Nancy template.

6-sample-solution

The template creates a module called IndexModule which returns a view called Index.

namespace TestingDemo
{
  using Nancy;

  public class IndexModule : NancyModule
  {
    public IndexModule()
    {
      Get["/"] = parameters =>
      {
        return View["index"];
      };
    }
  }
}

I then created an MS Test project called specs, and added the following test to make sure that when someone browses to “/” they would be served up the Index view

public void Should_Return_IndexView()
{
 //arrange
  var bootstrapper = new ConfigurableBootstrapper(with =>
  {
    with.ViewFactory<TestingViewFactory>();
    with.RootPathProvider<TestRootPathProvider>();
    with.Module<IndexModule>();
  });

  var browser = new Browser(bootstrapper);

  //act
  var response = browser.Get("/");

  //assert
  Assert.AreEqual("index", response.GetViewName());
}

To make this work I needed to implement my own custom IRootPathProvider,

public class TestRootPathProvider : IRootPathProvider
{
  public string GetRootPath()
  {
    string assemblyFilePath = new Uri(typeof(TestingDemo.IndexModule).Assembly.CodeBase).LocalPath;
    var assemblyPath = System.IO.Path.GetDirectoryName(assemblyFilePath);
    var path = PathHelper.GetParent(assemblyPath, 3);
    path = System.IO.Path.Combine(path, "TestingDemo");

    return path;
  }
}

In the Specs project I reference the TestingDemo project and then added the Nancy.Testing and Nancy Razor View Engine (since I’m testing Razor views) NuGet packages.

At this point the test passes in the visual studio test runner, but fails in NCrunch.

Eating Nancy tests with NCrunch

To get the tests to pass in NCrunch you will need to make a few changes to the NCrunch configuration for the test project.

  1. Open the NCrunch configuration window from the NCrunch menu and select the test project (below mine is called Specs)
  2. Under General select “Additional files to include”
    1-ncrunch-config
  3. Click the button with three dots (see highlighted in red above), on the Additional Files to Include dialog click “Add Directory”
  4. Browse to and select the root folder of your Nancy project, then click OK
  5. You will see the folder appear in the Additional Files To Include window, click OK2-additional-files-to-include
  6. Back in the NCrunch configuration window, under Build Settings set “Copy referenced assemblies to workspace” to True
    4-copy-references-assemblies
  7. You can now close the NCrunch configuration window

You should see that the test has now passed in the NCrunch Tests window

5-tests-have-passed

* May not actually change your testing habits.

Nancy Testing – Razor View with Referenced Models

The last few weeks I’ve been working with Nancy (an awesome web framework for .Net), the core goal of the framework is the super-duper-happy path:

The goal of the framework is to stay out of the way as much as possible and provide a super-duper-happy-path to all interactions.

This means that everything in Nancy is setup to have sensible defaults and conventions, instead of making you jump through hoops and go through configuration hell just to get up and running. With Nancy you can go from zero to website in a matter of minutes. Literally.

From the experience that I’ve had with Nancy to date, I would say it easily lives up to this goal for both development and testing. It is very easy to get started writing tests and most of what you need to know is covered in the docs.

However, on Friday I started experiencing a problem with some of our existing tests which check that the Razor view has been rendered correctly – by counting the number of rows in a <table>.

The cause of the failing test was that I changed the ViewModel to include a List of objects which live outside of the Web App assembly. To get my Nancy project to work when deployed I had to update the web.config file to include a list of assemblies for Nancy to reference when rendering the Razor views.

This morning I came back this problem afresh and found the solution 😀 Reading through the Razor View Engine docs on GitHub there is mention of the IRazorConfiguration:

You can specify assemblies and default namespaces that Razor needs to use whilst compiling the views by bootstrapping your own IRazorConfiguration implementation, thus removing the need to add the @using statements to each view. This step is totally optional if you don’t require additional references or namespaces in your view.

After trying various things I came across two different ways to get my tests to pass:

1. Update the App.Config file

This is the simple and easy solution, unfortunately I discovered this solution after the harder one below. On Friday I made the mistake of updating the web.config file which was in my Tests project and my tests kept failing – no surprise there.

What I should have done was update my App.Config file, after I did this all the tests passed.

Add the following section to the configSections group:

<section name="razor" type="Nancy.ViewEngines.Razor.RazorConfigurationSection, Nancy.ViewEngines.Razor" />

Then add the following to the end of the config file just before </configuration>:

<razor>
  <assemblies>
    <add assembly="Domain" />
    <add assembly="Some.OtherAssembly" />
  </assemblies>
</razor>

With that simple change my view tests passed. I guess the web.config file was added when I added the Nancy NuGet package.

2. Implement the IRazorConfiguration interface

The slightly harder solution is to implement the IRazorConfiguration interface and reference this when setting up the ConfigurableBootstrapper – the advantage of this is that you have finer controller over what is going on, the downside is that you will need to include this everywhere you are using the ConfigurableBootstrapper.

You will need to create a RazorConfigurationTestingStub which implements the IRazorConfiguration, mine looked like this:

internal class RazorConfigurationTestingStub : IRazorConfiguration
{

    public bool AutoIncludeModelNamespace
    {
        get { return true; }
    }

    public IEnumerable<string> GetAssemblyNames()
    {
        return new List<string>() { "Domain", "Some.OtherAssembly" };
    }

    public IEnumerable<string> GetDefaultNamespaces()
    {
        return Enumerable.Empty<string>();
    }
}

As you can see the list of Assembly names is the same list which was included in the App.Config file (in my Tests project) and the same list which is included in the web.config file (in my Nancy Web App project).

When setting up the ConfigurableBootstrapper you will need to include the stub as the implementation for the IRazorConfiguration dependency:

var bootstrapper = new ConfigurableBootstrapper(cfg =>
{
    cfg.ApplicationStartup((container, pipelines) =>
        {
            CookieBasedSessions.Enable(pipelines);
        });
    cfg.ViewFactory<TestingViewFactory>();
    cfg.RootPathProvider(new TestRootPathProvider());
    cfg.Module<Module.UnderTest>();
    cfg.Dependency<IThing>(thingInstance);
    <strong>cfg.Dependency<IRazorConfiguration>(new RazorConfigurationTestingStub());</strong>
});

After I did this all the tests passed.