Thursday, October 13, 2011

Easy vagrant setup on windows with chocolatey

Setting up vagrant on windows is well-documented and, overall, pretty easy. However, it is a little more complicated than just:
gem install vagrant
Luckily, us Windows developers recently got chocolatey. I just put together a few packages that makes vagrant setup on Windows a snap. To try it out just follow the chocolatey installation instructions. Then open a command prompt and run:
cinst vagrant
This command will download and install JRuby, VirtualBox, PuTTY, and the vagrant gem. It will also automatically set the registry keys for putty so that once you set up a box with vagrant you can SSH into it with:
putty -load vagrant
At this point the package comes with the old "works on my machine" stamp.


Check out the code on github or report an issue.

Update 11/10/2011:
More recent versions of the package will not modify the putty registry with the vagrant profile. Instead I recommend installing vagrant-putty.

Thursday, September 22, 2011

Enabling Pound proxy support for the HTTP methods PUT and DELETE

I'm not sure how many people out there are using Pound as a reverse proxy, but if you have it sitting in front of a ReSTful web service you may run into some issues with HTTP methods other than GET, POST, and HEAD. By default Pound only supports GET, POST, and HEAD. Pound will return an HTTP status code of 501 (not implemented) if it encounters a different method, such as PUT or DELETE.

Resolving this issue is easy. Each ListenHTTP or ListenHTTPS section in your pound configuration may contain the xHTTP setting. The default value for this setting is 0 (GET, POST, and HEAD). Setting the value to 1 adds support for PUT and DELETE. So putting it all together:

ListenHTTP
   # ... some settings
   xHTTP 1 #Support GET, POST, HEAD, PUT, and DELETE
   # ... some more settings
End

Happy proxying!

Monday, August 29, 2011

HTML Basics: Labels and inputs

I stumbled across some code the other day that made me smile. Here is essentially what was going on:

<input id="checkbox" type="checkbox" />
<label id="label" for="checkbox">My Label</label>

<script type="text/javascript">
$('#label').click(function() {
   var checkbox = $('#checkbox');
   checkbox.attr('checked', !checkbox.is(':checked'));
});
</script>

Naturally, this bit of javascript will toggle the checkbox's checked state whenever the label is clicked. There is nothing functionally wrong with this approach, except that it is wasted effort. Every browser I have ever worked with will do this automatically without any javascript. Simply associate a label with a checkbox (or radio button) and clicking the label will toggle the checkbox's checked state:


<input id="checkbox" type="checkbox" />
<label id="label" for="checkbox">My Label</label>

Sunday, March 27, 2011

Testing MySQL queries with NUnit

Even the most adamant unit-testing purist will admit that database queries need to be tested. If possible, these tests should run against the same database engine that will be used in production.

With a SQL Server database, testing queries is fairly easy, since most Visual Studio installations will include SQL Server Express. Just create the database in a SetupFixture, connect with Windows Authentication, and you're all set. MySQL presents a few more challenges, however. First, it needs to be installed. Second, the tests need the correct credentials to connect to the installed MySQL instance.

One simple way to handle this is to set up a central MySQL instance for testing only. However, this means team members must be on the network to run the tests. There is also the issue of multiple team members running the tests at the same time causing unexpected failures in each other's test runs, or worse, causing unexpected failures in an automated build.

A better alternative is to keep the MySQL binaries in version control with a known configuration that can be used in test runs. The binary distribution of MySQL is fairly large; however, with the right command line arguments, we only need two files: bin\mysqld-nt.exe and share\english\errmsg.sys (or whichever language you want to use). Include both of these as content files in a test project and set the build action to "Copy If Newer". In a SetupFixture, start MySQL with some code like this in the setup method:

var process = new Process();
var arguments = new[]
{
    "--standalone",
    "--console",
    "--basedir=.",
    "--language=.",
    "--datadir=.",
    "--skip-grant-tables",
    "--skip-networking",
    "--enable-named-pipe"
};

process.StartInfo.FileName = "mysqld-nt.exe";
process.StartInfo.Arguments = string.Join(" ", arguments);
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;

process.Start();

The first two arguments (--standalone and --console) tell MySQL to run as a standalone instance and to keep the console window open (i.e. do not run as a service). The next three arguments (--basedir=., --language=. and --datadir=.) tell MySQL to run from the current directory, load language files (errmsg.sys) from the current directory, and write data files to the current directory. The --skip-grant-tables argument disables security so that the tests do not need to worry about providing credentials when connecting. The final two arguments (--skip-networking and --enable-named-pipe) tell MySQL not to listen for TCP connections and instead allow named pipe connections. This prevents our standalone MySQL instance from interfering with any other MySQL installations on the machine.

Once the instance has started, we can connect with a connection string like this: Data Source=localhost;Protocol=pipe;. Finally, kill the MySQL process in the SetupFixture teardown method.

On my team, we have rolled this functionality (and a few other goodies) into a NUnit addin, but that's a story for another blog post.

Happy testing!

Thursday, February 10, 2011

NServiceBus assembly scanning: avoiding unintended consequences

The default startup behavior for a NServiceBus endpoint is to scan all assemblies in the deployment directory for any types it might be interested in, for example, message modules and message handlers. This is really handy, but occasionally it can lead to unintended consequences. Fortunately, the With method has a few overloads and one of them takes a list of assemblies to scan. If you want to prevent loading types from any stray assembly that might make it into your deployment directory, change your initialization code to look like this:

var assemblies = GetType().Assembly
   .GetReferencedAssemblies()
   .Select(n => Assembly.Load(n))
   .ToList();
assemblies.Add(GetType().Assembly);
NServiceBus.Configure.With(assemblies);

This restricts the assembly scanning process to only the assemblies that your endpoint explicitly references. We can extract this code to an extension method so we can use it in other endpoints:

public static IEnumerable<Assembly> ReferencedAssemblies(this Type type)
{
   var assemblies = type.Assembly
      .GetReferencedAssemblies()
      .Select(n => Assembly.Load(n))
      .ToList();
   assemblies.Add(GetType().Assembly);
   return assemblies;
}

Now our endpoint initialization looks like this:

NServiceBus.Configure.With(GetType()
   .ReferencedAssemblies());

Tuesday, December 21, 2010

Assert.DoesNotThrow... why does it exist?

Take a look at this test:

[Test]
public void TestSomething()
{
   Assert.DoesNotThrow(MethodUnderTest);
}

It seems to me that it is functionally equivalent to this test:

[Test]
public void TestSomething()
{
    MethodUnderTest();
}

In other words, Assert.DoesNotThrow is the same as writing a test with no assertion. Is it really enough that the code runs without throwing an exception? Presumably the method under test is doing something, so shouldn't you verify those results with a stronger assertion?

Tuesday, December 7, 2010

AsyncController and custom action invokers

If you are trying to get AsyncControllers to work, you might run into this gem when you try to test your controller:

The resource cannot be found

If this happens to you, a custom action invoker is likely to be the culprit. In my case, I was using Castle Windsor, and I had extended ControllerActionInvoker to provide dependency injection to my action filters. My action invoker looked something like this:



And this is how I had registered the action invoker with Windsor (this assumes you are using a controller factory that is aware of Windsor):




All I had to change to fix the problem was to make my custom action invoker inherit AsyncControllerActionInvoker instead:



AsyncControllerActionInvoker implements IAsyncActionInvoker and adds a few new methods. Depending on what you are trying to accomplish with your custom invoker, you may need to override a few of these new methods as well.

Interestingly enough, I did not have to change how the invoker was registered with Windsor.