MSpec v0.3

IMPORTANT NOTE: This is beta (still). The assertion library is new and may have bugs. I’d appreciate you testing it on your specs, but don’t fight specs breaking too hard if they do, let me know what happened and revert, I wouldn’t want to cost you your day chasing down a bug in MSpec. Thanks!

It’s been more or less forever since I’ve incremented the version number of MSpec so I went ahead and did it today. This is just a brief post to let you know what’s new and what I broke—maybe I’ll post some more detail later.

MOST IMPORTANT NOTE: v0.3 removes the dependency on NUnit/XUnit. If you’re upgrading, delete your Machine.Specifications.NUnit.dll and Machine.Specifications.XUnit.dll and remove their references from your projects. MSpec has an all new assertion library (with a bit of borrowed code from XUnit, turns out equality is hard).

I’ve attempted to format the new error messages to minimize debugging, so they’re rather verbose. Please let me know if they are too verbose or if there’s anything else you’d like to see.

You may need to tweak a few specs (ex. ShouldEquals is now generic, so you have to pass it the same type as the thing you’re observing) but most things should “just work”. Let me know if any of the new assertions give pain.

I also added a XCopy Deployable Test Runner manifest for TD.NET so no more fiddling with the registry or dealing with version issues. Pretty slick really. Thanks Jamie for pointing this out to me.

Of course there are plenty of other changes from 0.2 to 0.3 since it’s been like, a year. Here’s some others off the top of my head:

  • R# runners for 4.0, 4.1, 4.5 and 5.0 and they’re better than ever thanks to Alexander Groß.
  • Xml output from the command line runner with –xml for CC.NET/Hudson thanks to Barry Woods.
  • Concern is now Subject
  • There is no longer a difference between “Establish context” and “Establish context_once”, the context is always established only once. The idea is that observations are observations, they should not mutate state so there is no reason to execute the context more than once. Same for cleanup. If you *really* want to do execute the context for each specification, first try to change your mind, then if you still want it use: [SetupForEachSpecification] on your context class.
  • You can implement an IAssemblyContext in your spec assembly to set things up before or clean things up after all of your specs in that assembly have run.
  • You can implement a ICleanupAfterEveryContextInAssembly to perform cleanup after every context (think cleaning up static state, resetting your ServerClock/DateTime replacement for example.
  • Selenium RC support

Many thanks again to Alexander Groß for adding packaging to MSpec. You can now download builds from herewithout having to build it yourself! Just grab the Artifact from the latest build.

And, as always, the best way to get me is on twitter.

Posted in bdd, machine, mspec | 2 Comments

Machine.Migrations changes

Jacob first introduced Machine.Migrations over a year ago. Since then, it’s been a solid part of our process and we’re up to nearly 500 migrations with it on one project.

Recently, I finally got around to making some changes I’ve been wanting to make and I wanted to call’em out:

  • We split the repostiory out to its own on github. I did this similar to the way I did it for MSpec some time ago. Again, the advantage here is that change logs are localized to the project rather than the entire machine overarching project.
  • I added complaints if you have multiple migrations with the same number. This silently caused problems before as one of the migrations would not get applied. Now it just yells and dies like a good app. Of course, this is not as important because of the next change.
  • Next I added support for timestamped migrations. This helps immensely on active projects with multiple developers. You don’t have to deal with communicating migration numbers to the team when you add them, you just generate a new one and merge it when you feel like it. We actually had half of our topic on Campfire dedicated to our current migration number. The other half was who owed how many pushups for breaking the build.

    Here’s the rake task we use to generate a new migration:

    namespace :new do
      task :migration do
        raise "usage: rake new:migration name=\"Your migration name\"" unless ENV.include?('name')
    
        name = ENV['name']
    
        filepath = "db/migrate/#{Time.now.strftime('%Y%m%d%H%M%S')}_#{name.gsub(/ /,'_')}.cs"
    
        text = File.read("db/migrate/template.cs")
        File.open(filepath, 'w') { |file|
          file.puts text.gsub(/\$MigrationName\$/,"#{name.gsub(/ /,'_')}")
        }
      end
    end
    

    Usage is simple, just create a template.cs in the directory (we use db/migrate) and then type

    rake new:migration name="this is my migration name"

    Example template:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Machine.Migrations;
    
    public class $MigrationName$ : SimpleMigration
    {
      public override void Up()
      {
        throw new System.NotImplementedException();
      }
    
      public override void Down()
      {
        throw new System.NotImplementedException();
      }
    }
    
  • Finally, I added a command line runner. As we’ve grown more and more sick of msbuild and more and more fond of rake, we’ve wanted to slowly all but eliminate our dependency on MSBuild. The command line tool is quite simple:

    Machine.Migrations
    Copyright (C) 2007, 2008, 2009 Machine Project
    
      c, connection-string  Required. The connection string to the database to migrate
      t, to                 Applies or unapplies migrations to get to the specified migration
      u, up                 Applies migrations to the latest
      s, scope              The scope?
      d, directory          Required. Directory containing the migrations
      v, compiler-version   Version of the compiler to use
      debug                 Show Diagnostics
      r, references         Assemblies to reference while building migrations separated by commas
      t, timeout            Default command timeout for migrations
      ?, help               Display this help screen
    

    The only two flags you usually need are -c and -d. Just pass in the connection string and the location of your migrations. Be sure to quote them: migrate.exe -c “my connection string” -d “my migration directory”.

  • Hopefully these changes help others. Grab the latest here and just msbuild the sln to build it.

    I do wonder though, what other active .NET migration projects are people using and how do you like them?

Posted in machine, migrations | 5 Comments

Building an iPhone app

Today we launched PicTranslator, a free Picture Translator for the iPhone. Building it was quite an adventure. I wanted to share some of the technologies we used, you may be surprised.

On the iPhone:

  • iPhone SDK: This one’s obvious. Unfortunately, MonoTouch wasn’t out when we started to develop. It looks rather promising.
    To be perfectly honest though, Objective-C is pretty cool. Especially once you figure out it’s memory management scheme. It’s kind of fun to be back in pointer land again. Brings back fond memories. Oh, and though I did miss vim, xcode is a pretty darn good little editor.
  • json-framework: This is a pretty slick JSON parser for the iPhone. Hand parsing JSON in obj-C would not have been fun. This made it easy. I’m pretty sure I followed this tutorial to get it up and running.
  • ASIHttpRequest: Nice Http framework, helpful for doing asynchronous requests and sending and receing files easily.
  • We also used a few random snippets found around the web. Here’s one on rounded corners. Also stackoverflow was invaluable.

On the server:

  • nServiceBus: NSB is fantastic. It allows us to scale to any size machine or any number of machines. I’m realizing more and more than most reasonable size applications should leverage messaging in one way or another. We’re using MSMQ as the transport.
  • ASP.NET MVC: My web framework of choice.
  • MSpec: Gotta test it somehow right, why not use my own framework.
  • Topshelf: Best way I know of to create services in .NET. Makes it easy to run as a console app or a service. Love it.
  • log4net: Another no brainer. log4net is how you log in .NET. Well, most of you any ways :).

Not a bad stack, eh? Any surprises? Oh, and if you have an iPhone, be sure to give PicTranslator a shot, we’d love your feedback.

Posted in asp.net mvc, iphone, list, mspec | 9 Comments

Advanced Selenium RC logging with MSpec

Today I pushed some new features to MSpec to allow you to see this in MSpec’s html report when you get Selenium RC failures:

2009-10-19_1810

This is very similar to ruby’s selenium client’s rspec report. You can see a real example of that here.

So how do you get this? It’s pretty easy. All you need to do is grab and build the latest MSpec, add a reference to Machine.Specifications.SeleniumSupport.dll and add a class like the following to your assembly that contains your selenium specs in it:

  public class SeleniumSupport : SeleniumResultSupplementer
  {
    protected override string ImagesPath
    {
      get { return GetTempPath(); }
    }

    protected override DefaultSelenium Selenium
    {
      get { return ...; } // Replace with the DefaultSelenium in use 
                          // by the current running spec
    }

    static string tempPath;

    private static string GetTempPath()
    {
      if (string.IsNullOrEmpty(tempPath))
      {
        tempPath = Path.Combine(Path.GetTempPath(), "selenium");

        if (Directory.Exists(tempPath))
        {
          Directory.Delete(tempPath, true);
        }

        Directory.CreateDirectory(tempPath);
      }

      return tempPath;
    }
  }

That’s pretty much it. Like I said, this is brand new, just got it up today so please let me know if you have any problems with it. You can do so on twitter or the machine google group. Enjoy!

Posted in mspec, selenium | Leave a comment

A recent conversation about MSpec practices

Recently I’ve heard about more and more people checking out MSpec. A few days ago I got an email from a friend. He said he was having trouble with base class explosion while creating specs. Here is a snippet from his code:

public abstract class with_null_program
{
  protected static Program program;
}

public abstract class with_program_and_empty_args : with_null_program
{
  Establish context = () => program = new Program(new string[]{});
}

public abstract class with_list_command
{

}

[Subject("Program")]
public class when_creating : with_program_and_empty_args
{
  private Because of = () => program = new Program(new string[] {});

  It should_output_to_the_console =()=> 
   program.Out.ShouldEqual(Console.Out);
}

[Subject("Program")]
public class when_running_with_no_arguments : with_null_program
{
  private static StringBuilder outputBuilder;

  private Because of = () =>
  {
    outputBuilder = new StringBuilder();
    program = new Program(new string[] {}) {Out = new StringWriter(outputBuilder)};
    program.Run();
  };

  It should_print_usage =()=> outputBuilder.ToString().ShouldContain("USAGE");
}

[Subject("Program")]
public class when_running_without_database_args : with_list_command
{

}

And here’s my response:

Hey man, Glad to see you playing with MSpec. Definitely curious to get your feedback on the experience.

So there’s a few things I noticed about the specs. For one, you’re using the with_ pattern. I know I or Scott or someone started this… but I don’t like it now. I much more prefer to just have a base class that contains any utility/meaningless cruft my specs have. You also seem to have taken this to a bit of an extreme. Would you make a regular base class just to create a single instance variable and set it to null in the constructor? Probably not. Same stuff applies here. There’s no value in creating base classes unless they provide value. There’s no naming or understanding benefit. As a matter of fact, they *hinder* understanding more than anything. This is why I try to only put utter crap in base classes, and when it’s important crap, I put it in a method and name it something descriptive and call it in the context. If I were to rewrite these specs I *may* have a single base class called ProgramSpecs. It would probably just have the static program field, but be a place holder in case i needed any utility methods. Naming specs with the with_foo_bar implies that that name is important, which it isn’t. It’s not included in the report for a reason. Your context description should be fully encapsulated by the name of the context class.

Another thing I’m seeing… and I’m not sure if this is just circumstantial, but do you know that you can have more than one context in a class hierarchy? In other words, something like outputBuilder = new StringBuilder() would go in the subclasses establish context. They’re run in order from basiest to subbiest. The Because is *only* a way to highlight a line and say "this is the catalyst that makes the observations possible… everything else up to this point is also important, but this is the real meat". Because is actually *part* of the context. The Context is the arrange and the act (if there is an act). Here’s an example of multiple context clauses (though i have no idea why i didn’t use because here, heh): http://github.com/aaronjensen/compete/blob/master/Source/Compete.Specs/Model/Game/AggregateResultSpecs.cs

As an aside, I feel the Program class is a bit awkward. Personally, it’d make more sense if the StringBuilder was a constructor parameter and the args were parameters to the run method. That’s just my style though–i’m not saying it’s better. It would definitely make testing this less awkward. Actually, look at your context. "when running with no arguments". Your code isn’t doing what you said it would do, at least not in the simplest fashion. I think I’ll change my position to "strongly prefer" the arguments to be passed to the Run method :) More often than not, when you’re feeling pain while testing it’s because your API can be improved.

You may, if you haven’t already, want to take a look at the mspec console runner specs: http://github.com/machine/machine.specifications/blob/master/Source/Machine.Specifications.ConsoleRunner.Specs/ProgramSpecs.cs

They’re quite similar to the domain you were writing specs for and may help. Yes, I used with_runner there, they’re old ;)

Hope that helps a bit, let me know if you have any other questions or anything.

Thanks, Aaron

Posted in mspec | 19 Comments