Development Blog

 Thursday, May 08, 2008

Just wanted to quickly note that I tracked down the performance issue in Rhino.Mocks and patched it. I also updated the original post with the new numbers. Enjoy!

by Aaron on Thursday, May 08, 2008 9:56:48 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
UPDATE: I tracked down the issue and committed a patch to Rhino.Mocks. Rhino.Mocks is now much more competetive performance wise, our CI build time nearly halved, and about 4 minutes out of 7 of our test time has disappeared. New numbers below.

I've complained before that Mocking is Slow but I never really dove further into it. Today I decided to actually compare Rhino.Mocks to other mock frameworks on a pure performance basis to see if it was a global problem. I timed 2000 unit tests across 100 classes with 20 tests each. The results were a bit surprising:

Framework TD.NET Time nunit-console Time
Rhino.Mocks old trunk 57.36s 28.82s
Rhino.Mocks new trunk 22.94s 7.59s
Moq trunk 18.30s 5.91s
TypeMock 4.2.3 Reflective Mocks 15.36s 9.35s
TypeMock 4.2.3 Natural Mocks 16.92s 9.56s

That's right, according to these tests, Rhino.Mocks is at least 3 times slower than the other frameworks when under heavy load in TD.NET and five times slower in the console according to these tests. It's also interesting to note that TypeMock is faster than Moq in TD.NET, but slower in the console runner.

While running the Rhino.Mocks tests it is very clear that there is a degrading performance issue. All the other frameworks executed tests with a near constant speed per test, but Rhino.Mocks slowed down noticeably about half way through.

Please feel free to try it yourself, grab the project here. You should be able to just run the 4 strategy .bat files (run-rhino, run-moq, run-tmock-reflective, run-tmock-natural). Let me know if you find anything interesting.

by Aaron on Thursday, May 08, 2008 7:52:30 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback

As some of you who follow me on twitter know, I've been working on Yet Another Context/Specification Framework as an experiment. Yeah, I know we already have NSpec and NBehave, and they're great and all, but MSpec takes things on from a slightly different angle, and it's just an experiment (for now). Here's a sample Description:

[Description]
public class Transferring_between_from_account_and_to_account
{
  static Account fromAccount;
  static Account toAccount;

  Context before_each =()=>
  {
    fromAccount = new Account {Balance = 1m};
    toAccount = new Account {Balance = 1m};
  };
  
  When the_transfer_is_made =()=>
  {
    fromAccount.Transfer(1m, toAccount);
  };
   
  It should_debit_the_from_account_by_the_amount_transferred =()=>
  {
    fromAccount.Balance.ShouldEqual(0m);
  };

  It should_credit_the_to_account_by_the_amount_transferred =()=>
  {
    toAccount.Balance.ShouldEqual(2m);
  };
}

And a TestDriven.NET run:

------ Test started: Assembly: Machine.Specifications.Example.dll ------

Transferring between from account and to account
  When the transfer is made
    * It should debit the from account by the amount transferred
    * It should credit the to account by the amount transferred


2 passed, 0 failed, 0 skipped, took 0.79 seconds.

Err, What?

Different eh? The idea was heavily inspired by Scott Bellware's SpecUnit.Net framework he showed at the ALT.NET conference. It also took heavy cues from RSpec and my insanity. I realize that the the code doesn't look much like C# code and I'm OK with that. Many have and will ask why I don't just use Boo or RSpec w/ IronRuby eventually or even one of the existing Context/Spec/BDD frameworks. Those are good questions, but my main motivations are tooling and syntax. I enjoy the tooling I get in C# and I personally like the syntax in this library considering the limitations imposed by C#.

How's it work?

The simplest way to describe it is to compare it to a normal *Unit style testing framework:

  • Description = TestContext
  • Context before_each = SetUp
  • Context before_all = SetUpFixture
  • Context after_each = TearDown
  • Context after_all = TearDownFixture
  • When = Also SetUp, but happens after Context before_each
  • It = Test

Rather than methods and attributes, MSpec uses named delegates and anonymous functions. The only reason for this is readability. You'll also notice that the fields used in the context are static. This is necessary so that the anonymous functions in the field initializers can access them. Probably the first thing you noticed is the =()=> construct. I won't mention the names that this was given on twitter, but I think it's an acceptable thing to have to deal with in exchange for the cleanliness of the rest of the syntax.

Ok, you're crazy, but how do I try it?

First, this is a very rough cut. Everything is subject to change as we experiment with the language. That said, here's how you play with it:

  1. Grab the drop here.
  2. Extract it somewhere. Put it somewhere semi-permanent because the TestDriven.NET runner will need a static location for the MSpec TDNet Runner.
  3. If you want TestDriven.NET support, run InstallTDNetRunner.bat
  4. Check out the example in Machine.Specifications.Example. Note that you can run with TD.NET.
  5. Create a project of your own. Just add Machine.Specifications.dll and get started.
  6. Send me feedback! Leave comments, email me, tweet me, whatever.

Also, this is part of Machine, so feel free to take a look at the code and/or submit patches. There's also a Gallio adapter in there, but I didn't include it in the release as it's not quite polished enough yet. If you're interested in it, talk to me. Special thanks to Scott Bellware, Jeff Brown and Jamie Cansdale for their help and support.

by Aaron on Wednesday, May 07, 2008 11:11:27 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [8]  |  Trackback
 Friday, April 25, 2008

Introduction

We used ActiveRecord migrations at Eleutian for a number of months. Everything was right with the world and we had no major complaints until we started running into a problem with our more complex migration scenarios. Usually, we see two kinds of migrations:

  • Schema - Add/remove/rename columns, manipulate tables, and general schema related changes.
  • Data - Refactoring data into new schemas and major data reorganization or population.

Schema migrations are handled great by most of the migration frameworks out there. One problem we were running into was it's typically easier to write the data migrations in C# directly using our entities and services. As a result we had two different ways of migrating and this made our frequent publishes problematic. We decided to consolidate the two operations.

On the outside there's nothing really new in Machine.Migrations that you haven't seen elsewhere. Most of the changes are internal. Migrations are numbered right now, although we've talked of moving to time-stamping them a la the newer ruby ActiveRecord. What Machine.Migrations does allow you to do is heavily tweak your migrations to fit your project. In our project we have a custom MsBuild task that extends the default implementation to provide access to our DaoFactory and other goodies. If this is something that interests you, then read on. If you're happy with your current migration scenario then you probably don't have a huge need for Machine.Migrations.

A Simple Migration

I'll start with the actual migrations. Here is an example that creates a table:

using System;
using System.Collections.Generic;
using Machine.Migrations;

public class CreateUserTable : SimpleMigration
{
  public override void Up()
  {
    Schema.AddTable("users", new Column[] {
      new Column("Id", typeof(Int32), 4, true, false),
      new Column("Name", typeof (string), 64, false, false),
      new Column("Email", typeof (string), 64, false, false),
      new Column("Login", typeof (string), 64, false, false),
      new Column("Password", typeof (string), 64, false, false),
    });
  }

  public override void Down()
  {
    Schema.DropTable("users");
  }
}

Machine.Migrations does enforce a file naming/class naming restriction so the file for this migration would be named 001_create_user_table.cs. We inherit from SimpleMigration, which is built-in and provides access to Schema manipulations and raw Database queries through those properties respectively. We have a solution and project for our migrations so that we can get IntelliSense while writing them. This can be helpful if you forget the syntax.

When you run Machine.Migrations it will only compile the migrations that it needs to apply. This is very handy if you are doing high-level migrations including your entities because then you don't have to maintain them after they've been applied to your live database. But, this does mean you won't be able to migrate from the beginning to the end because migrations will become outdated. This has been a minor problem for us because we snapshot our live database and run that in development. I do think a better long term solution is required though, in order to make creating a brand new database easier. Perhaps flagging migrations as data migrations and not running them if they don't compile? I am not sure.

There is also a Boo migration factory that you can use if you don't want to write your migrations in C#. Internally, the infrastructure is there if you want to add other languages as well.

Another interesting thing I should note is that each migration is run inside its own transaction, so if you mess up it'll just rollback. This is very nice under SQL Server because schema changes are rolled back as well.

How Do I Start Using It?

If you just want to use Machine.Migrations out of the box (a good first step) it's fairly straightforward:

  1. Copy Machine.Migrations and its dependencies into your project. Be sure to include the Machine.Migrations.targets file which has the default MsBuild task and target.
  2. You can then drop the following XML into your MsBuild file (check all your paths!):
    <Import Project="Libraries\Machine\Machine.Migrations.targets" />
    
    <PropertyGroup>
      <MigrationConnectionString>Data Source=127.0.0.1;Initial Catalog=MyDb;Integrated Security=SSPI</MigrationConnectionString>
    </PropertyGroup>
    
    <Target Name="Migrate" DependsOnTargets="MigrateDatabase">
    </Target>
  3. All that's happening here is we're importing the targets file, defining a connection string to use when migrating, and then making a target that depends on the target we imported.
  4. By default it will look for your migrations in a subdirectory named Migrations.
  5. Then it's just a matter of running MsBuild YourProject.proj /t:Migrate where YourProject.proj is your MsBuild file.

One thing you may notice is that sometimes your migrations will fail to compile because of a missing dependency. In order to ensure your own or third party assemblies are referenced you add them to the MigrationReferences ItemGroup, like so:

<ItemGroup>
  <MigrationReferences Include="System.Xml.dll">
    <InProject>false</InProject>
  </MigrationReferences>
</ItemGroup>

When Machine.Migrations compiles it will include those assemblies in the references list.

What Next?

I'm going to hold off on explaining how to extend the default migration scenario until later because this post is already pretty long. For anyone feeling ambitious it basically amounts to extending SimpleMigration in your own code and inheriting from that. (Be sure to include your assembly in MigrationReferences). We go a step further and wrap the MsBuild task as well, which may or may not be necessary for you.

I can't stress enough that going down this road isn't for everybody. There is an argument for keeping migrations simple and making those complex data migrations something else's concern. For now, this is what we're doing and it has worked nicely. I'm sure there will be lots of questions as well, please feel free to comment and offer up suggestions. As far as I know we're the only people using this code, so I'm sure there are quirks.

by Jacob on Friday, April 25, 2008 12:37:26 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, April 16, 2008

One idea I've been thinking about lately is that good tools get out of your way. I started thinking about this after reading an article about photography and fancy equipment. A few days later I was upgrading my ReSharper to the latest EAP and started thinking about how the same principal applies to my tools in software development.

I've been a huge fan of ReSharper for a long time. It and ViEmu are an absolute necessity for me when doing any kind of work with C#. After we first installed it at work we would joke that it just knows what you want to do. When I use a new tool I usually don't see the value right away and to help others see the value faster I'm going to give a short list of the features I personally use constantly. Here is my list for ReSharper:

  1. Error Highlighting: Anything that saves me from a failed build saves me tons of time.
  2. Quick-Fix (Alt-Enter): Import Type and Initialize field from constructor(s) parameter. I use one of these every minute it seems. I also like that I can disable things. For example, I disable "Redundant this qualifier", that's how I roll.
  3. Generate (Alt-Ins): I usually generate properties and constructors with field initializers.
  4. Refactor: Move Type to File, Rename
  5. Ctrl-Alt-Space: Complete Type Name from any namespace, imported or not.
  6. Find Usages: I like that it keeps a history of past searches and that I can group things by project/namespace. It crosses usages out when I change things too, which is helpful.

It can do a lot more than this. What's particularly important is that I never know I'm using another tool. I rarely see dialogs popup and break my flow, that sort of thing. It gets out of my way. I'm always looking at my code. That's important because it's what I'm doing. Do your favorite tools get out of your way? While I have an audience I'm going to ask for a couple of things:

  1. I would love to be able to set my IntelliSense to default to Ctrl-Alt-Space mode when completing a type name. I'm trying to avoid having to go into that mode manually.
  2. When generating code (properties, constructors, etc...) there's a second dialog now that lets you set properties on the generated members. I would like to disable this second dialog, I'll never use it. It's much faster for me to manually tweak the generated code using my Vim-Fu.

Are either of these things possible already? Also, before you go, I think it's good to know which specific things people find particularly useful about their tools. If you have any features of any tool that you use several times a day, I'd love to hear what they are. Maybe I'm missing out on something.

Also, I'll be in Seattle for ALT.NET so come up and shake my hand!

by Jacob on Wednesday, April 16, 2008 3:42:40 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Sunday, April 13, 2008

Currently in Rhino.Mocks, making mocks fire events and ensuring that an event on your SUT was fired are both awkward and verbose at best. Here is an example of both things at once:

[Test]
public void ViewFiresBeginDrag_Always_FiresChangedEvent()
{
  IEventRaiser raiser;
  bool eventFired = false;
  using (Record)
  {
    The<ICardView>().BeginDrag += null;
    raiser = LastCall.IgnoreArguments().GetEventRaiser();

    Target.Changed += (x,y) => eventFired = true;
  }

  using (Playback)
  {
    raiser.Raise(The<ICardView>(), EventArgs.Empty);
    Assert.IsTrue(eventFired);
  }
}

Nice eh? First, is there a better way to do either of these things that I'm missing? Please tell me if so. Next, if not, what can we do to clean this up?

Well, Ayende and I discussed this in the past and Ayende spiked it and asked for feedback. The feedback was mixed and for one reason or another it never made it into Rhino.Mocks that I know of.

Well, today while I was working on Machine.Testing and another side project, I decided to give something else a shot. What I ended up with is this:

[Test]
public void ViewFiresBeginDrag_Always_FiresChangedEvent()
{
  using (Record)
  {
    PrimeEventFiringOn<ICardView>(x => x.BeginDrag += null);
    Target.Changed += NewEventFireExpectation<EventHandler>();
  }

  using (Playback)
  {
    FireEventOn<ICardView>(EventArgs.Empty);
  }
}

Better, but I still don't think it's perfect. Also, it probably requires some explanation, so let's pick it apart piece by piece:

    PrimeEventFiringOn<ICardView>(x => x.BeginDrag += null);

=> +=??? Ugly huh? I really wish we could just refer to an event somehow without having to do +=/-=. At least I'm not using vb though... Alas, we cannot access them easily so we're stuck hacking away like this. So this particular method will basically get the mock or stub ICardView.BeginDrag ready to be fired. This needs to be done during the record phase it seems. You can only prime one event at a time per mock, so if you need to do more than one you can revert to the normal Rhino.Mocks syntax.

    Target.Changed += NewEventFireExpectation<EventHandler>();

This was a fun method. This method actually creates a new DynamicMethod in the signature required by the event and creates a new delegate. The method tracks whether or not it was fired, and at the end of the Playback phase in my fixture it will assert that all of the events were actually fired.

    FireEventOn<ICardView>(EventArgs.Empty);

This actually fires the event we set up in the Prime call. It can only be called after you've primed an event.

So, the whole thing is kind of "magic", but it's less code if you can accept the magic. I think we can make things even better though, but it'd require changes to Rhino.Mocks and it's time for bed so maybe Ayende can swing by the Eleutian office while in Seattle and we can work on it. Here's what I'm thinking:

[Test]
public void ViewFiresBeginDrag_Always_FiresChangedEvent()
{
  using (Record)
  {
    Target.Changed += Mocks.CreateEventHandler<EventHandler>();
  }

  using (Playback)
  {
    EventRaiser.Raise(() => The().BeginDrag += null, The<ICardView>(), EventArgs.Empty);
  }
}

There's probably more you can do with the CreateEventHandler syntax like add more specific expectations, assert its not fired, assert that it's fired X times, etc. The EventRaiser syntax is ugly, but it doesn't involve strings or the fire from the right hand side like the syntax I mentioned at the beginning of the post.

You can get the source here, but I warn you it's first draft and there are hacky bits.

Oh, and here's some example tests using the TestsFor fixture:

[TestFixture]
public class CardPresenterTests : TestsFor<CardPresenter>
{
  private Card _card;

  public override void SetupContainer()
  {
    Override<ICardView>(With.Stub);
  }

  public override void BeforeEachTest()
  {
    _card = new Card(0);
  }

  [Test]
  public void OnBeginDrag_Always_SetsIsInFluxToTrue()
  {
    using (Record)
    {
      PrimeEventFiringOn<ICardView>(x => x.BeginDrag += null);
    }

    using (Playback)
    {
      FireEventOn(EventArgs.Empty);

      Assert.That(The<ICardView>().IsInFlux, Is.True);
    }
  }

  [Test]
  public void OnBeginDrag_Always_FiresChangedEvent()
  {
    using (Record)
    {
      PrimeEventFiringOn<ICardView>(x => x.BeginDrag += null);
      Target.Changed += NewEventFireExpectation<EventHandler>();
    }

    using (Playback)
    {
      FireEventOn<ICardView>(EventArgs.Empty);
    }
  }
}
by Aaron on Sunday, April 13, 2008 12:30:10 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Wednesday, April 09, 2008

Some time ago, Packt Publishing sent me a copy of Hacking Vim: A Cookbook to get the Most out of the Latest Vim Editor by Kim Shulz to review. I read through it pretty quickly and I must say I thought it was a good book for the most part. The book is definitely focused at a very niche audience as there aren't a lot of us Vimmers around. Furthermore, I can't say I'd recommend the book for the casual Vimmer or those that use only ViEmu in Visual Studio. If, however, you are a moderate to hardcore Vim user or are interested in becoming one I would definitely recommend grabbing a copy.

There is a lot of information in this book. It wastes no time or space describing the many ways to make your Vim experience even more efficient than it already is. Because of its very cut and dry style it reads more like a reference book than anything else, but I think that's perfectly fine for this style of book. It is essentially a slightly more readable, more detailed and better written version of a lot of the Vim help. It's also nice because in many of the chapters, especially the first few ("Better Navigation" and "Production Boosters") you can pick up a lot of interesting tips. I even learned a few handy commands I had no idea about.

There's plenty of good information on writing Vim plugins and customizing Vim that I wish I would have had six years back when I wrote Vim plugins. Ah, looking at that code brings back fond memories, mostly involving learning Regular Expressions through trial and error and I actually used /// comments in C# code, but I digress.

I also liked the stuff on firing Ruby from Vim--it reminded me I need to get a Ruby environment set up in Vim. Oh, and just for fun it seems, Kim even included an appendix showcasing some of the ridiculous things that have been written for Vim like Nibbles and Rubik's Cube. Heck, I just found a Twitter client for Vim (yea, I twitter now in case you care).

There are a few things wrong with it though. Some things are too close to the Vim built-in help and you're probably better off just looking there. Also, the index isn't very useful and it'd be nice to have a searchable version of the book as well, so maybe the eBook version is a good idea. I wish all book companies would bundle eBooks with paper books, but, I digress again. Like I said, there is a lot of information in this book. It's not for everyone, but I think most Vim users will find plenty of useful stuff in its pages.

reviews | vim
by Aaron on Wednesday, April 09, 2008 9:02:56 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, April 03, 2008

Daniel Cazzulino, author of Moq posted a good comment on my last post where I suggested looking into a Mockito like syntax for .NET Mock Frameworks.

On the surface, Mockito's approach seems good. But if you do the "true" comparison, you'll see that stub(...) is exactly the same as mock.Expect(...) in Moq.

Then, when you do verify(...), you have to basically repeat the exact same expression you put in stub(...). This might work if you only have a couple calls to verify, but for anything else, it will be a lot of repeated code, I'm afraid.

I thought this too. See my comment here from a month ago. Szczepan made a good point and I've thought about it more since then.

When combined with my position on loose vs strict mocks (almost always use loose), I'd say that *most* of the time you are either stubbing or verifying. Meaning, if you're verifying you don't need to stub unless of course that method returns something that is critical to the flow of your test, in which case you don't really need to verify, because the flow would have verified. That's a mouthful, but does that make sense?

I haven't used mockito, and I know there are times I use Expect.Call with return values that matter (which would essentially require you to duplicate stub & verify), but maybe that's a smell? Maybe if you think you need that you can do state based testing or change your API?

Here's an example Test using Rhino.Mocks:

[Test]
public void SomeMethod_Always_CallsSendMail()
{
  IMailSender sender = mocks.DynamicMock();
  UnderTest underTest = new UnderTest(sender);

  using (mocks.Record())
  {
    Expect.Call(sender.SendMail()).Returns(true);
  }

  underTest.SomeMethod();

  mocks.Verify(sender);
}

And some code this is testing (obviously not test driven, but you get the idea):

public void SomeMethod()
{
  if (!_sender.SendMail())
  {
    throw new Exception("OH NOS");
  }
}

Notice that here we would need to stub and verify separately with Mockito like syntax. This would look something like this:

[Test]
public void SomeMethod_Always_CallsSendMail()
{
  IMailSender sender = mocks.DynamicMock();
  UnderTest underTest = new UnderTest(sender);

  Stub.That(() => sender.SendMail()).Returns(true);

  underTest.SomeMethod();

  Verify.That(() => sender.SendMail()).WasCalled();
}

This may violate DRY, but what if you designed your API differently? Maybe SendMail should throw an exception on failure instead of returning a boolean? This would make the return value unnecessary and remove the need for the Stub call. Clearly you can't always do this, especially with unwrapped legacy or API code, but it's something to think about.

Also, I think you shouldn't be verifying more than one method generally to go along with the one assert/test rule, so a single repeat would not be that horrendous. Heck, you could even do:

[Test]
public void SomeMethod_Always_CallsSendMail()
{
  IMailSender sender = mocks.DynamicMock();
  UnderTest underTest = new UnderTest(sender);

  Stub.That(var sendMail = () => sender.SendMail()).Returns(true);

  underTest.SomeMethod();

  Verify.That(sendMail).WasCalled();
}

I think the syntax would lead to better, more concise tests. But maybe it would just be too annoying? I wouldn't know until I tried it for a while I guess.

by Aaron on Thursday, April 03, 2008 8:44:29 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, April 02, 2008

(Note: I'm going to speak about .NET mock projects here for the most part, but most of them have Java quasi-equivalents.)

The original mocking frameworks like NMock required you to setup expectations by passing strings for method names. This was fragile and made refactoring more difficult.

A few mock frameworks now allow you to define expectations and mock results in a strongly typed manner. Rhino Mocks and TypeMock use a record/replay method to setup expectations. The record replay method is mostly necessary because the same calls are made on the same objects under two different scenarios. This leads to a few issues.

The first issue is confusion and barrier to entry. Many people have complained that the Record/Replay method is not straight forward and the whole paradigm is confusing. There are also complains about the naming, are you really recording and then replaying? It's just kind of a strange thing. Of course most of us learn to live with it, understand it, and accept it for what it is. Recently though, a few mock frameworks have popped up that do away with this model.

In the .NET world we have Moq. Moq gets rid of the need for record/replay because recordings have a very different syntax. They use lambdas instead of actual calls to the mock object. This allows the framework to know when you are recording an expectation and when you are fulfilling an expectation. It adds a bit of noise in the form of "() =>" but all in all it's not bad. Of course this requires C# 3.0, but it's good to keep looking ahead.

In the Java world we have Mockito. Mockito also does away with the record/replay model but it does it in a different way. At first I wasn't a fan, but thinking about it more, I like it. Mockito has two main apis, stub and verify. Stub is equivalent to SetupResult.For, and verify is equivalent to Expect.Call with a verify. The interesting bit is that the stubbing happens before the the class under test is invoked and the verifying (which includes describing the method to be verified) happens after the class under test is invoked. This is best shown with an example stolen from the Mockito site:

  
  //stubbing using built-in anyInt() argument matcher
  stub(mockedList.get(anyInt())).toReturn("element");
  
  //stubbing using hamcrest (let's say isValid() returns your own hamcrest matcher):
  stub(mockedList.contains(argThat(isValid()))).toReturn("element");
  
  //following prints "element"
  System.out.println(mockedList.get(999));
  
  //you can also verify using argument matcher
  verify(mockedList).get(anyInt());

Obviously it would take a bit of imagination to arrive at a .NET equivalent, but you get the idea. I like this because the normal test structure is Setup Stuff->Do Stuff to Test->Verify Stuff did what it should have. The normal record/replay model requires you to set up verifications before you actually Do Stuff (though you call VerifyAll afterwards). This is a bit less natural. I feel syntax like this (yeah, I like the new NUnit syntax) would be more intention revealing:

Assert.That(() => someMock.Foo(), Was.Called);

Or:

Verify.That(() => someMock.Foo()).WasCalled();

Then you would stub like this:

Stub.That(() => someMock.Bar()).Returns(3);

Note: No idea if this is feasible or makes sense or not, my lambda experience is limited to light reading, but you get the idea. I'm sure the syntax could also be prettier.

Rhino.Mocks is my current mock framework of choice. I'm used to it, I've lightly contributed to it, and I've been working with it for a while now. Despite that, I do think that there is definitely more to explore in the mocking arena especially with C# 3.0.

There are lots of other fun things to talk about too... like TypeMock's magic, but that's another day still...

by Aaron on Wednesday, April 02, 2008 8:13:18 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [3]  |  Trackback

Recently, Aaron talked about how we keep a published branch. Lately, we have also been having to branch our code more frequently in order to work on big messy changes without disturbing ongoing development in the main trunk. Branching  is a great tool to use in those situations, but many find themselves cursing the day they decided to branch when they run into a billion conflicts when trying to merge their changes back to the trunk. Well....it doesn't have to be like that! So to help out those who've had nightmarish merge experiences, or to ease the fears of those who have yet to delve into the mysterious world of subversion branches and merges,  I have decided to share my thoughts on proper branching technique.

What is Branching?

Let's start with the basics. What is branching? Why would we need to ever do it? Well...everyone knows the golden rule of using version control systems is to "Check in often".  Checking in often gives us more flexibility if we make a mistake and want to go back to a previous version, and it also helps minimize conflicts when several developers are working on the same piece of code. However, as good a practice as checking in often might be, sometimes it's just hard to do, especially if we need to make a big all-or-nothing type change that will take us an extended period of time. In the meantime we can not afford to check in our half-completed change, because it would break things and prevent or make it very difficult for other developers to keep on working on their own stuff. Luckily however, we can simply make a copy of the current trunk repository and then check in our changes to this copy. We can now check in as often as we'd like without disturbing anyone. When we are done with our big change, we can merge it all back at once and everyone is happy. We call this copy a "branch".

How do we Branch?

Branching is easy. Subversion does not really have a built-in concept of a "branch". A branch is simply a copy of the your projects directory in the subversion repository. Where you copy it to is entirely up to you, but a good convention is generally a directory structure like:

MyProject/
         Trunk/
         Branches/
	          BranchName/

The URL for your main repository would look something like:

https://svn.server.com/svn/MyProject/Trunk

while the URL for your branch would be:

https://svn.server.com/svn/MyProject/Branches/BranchName

To create the branch we would simply use the subversion cp command:

svn cp https://svn.server.com/svn/MyProject/Trunk https://svn.server.com/svn/MyProject/Branches/BranchName

now we could simply check out the new branch:

svn co https://svn.server.com/svn/MyProject/Branches/BranchName

and work on it to our heart's content Any changes we committed would go to the branch and not disturb our main trunk code.

Keeping the Branch Up to Date and Merging

Now, here is the tricky part that many people screw up. While the whole point of the branch is to keep changes we make on the branch isolated from trunk, we DO NOT want to keep changes that are going on in trunk isolated from the branch. This is a recipe for disaster...or rather... a very painful merge. You see, the longer we keep the branch completely isolated from trunk, the greater the likelihood that nasty conflicts will happen.

The idea then is to take the changes that are going on in our project's trunk and apply them to our branch. Sure, this won't guarantee that you won't see any conflicts, but it is exponentially easier to resolve conflicts incrementally as you go along than to let them pile up until the end when you've already forgotten what the heck you were actually doing in the code that is now conflicting.

Enter the "merge" command. I think a lot of people misunderstand what this command does because it's name is misleading and makes it seem more mysterious than it actually is. I personally think this command should be renamed "diff and patch", because that is exactly what it does.

So how do we we use the merge command in order to keep the branch synchronized? Well, first of all let's talk about what we are trying to do. Say we were at revision 100 when we did the "svn cp" command that created our branch. Then we worked on our branch a few hours, did several commits to it. Meanwhile, other developers have continued working on trunk and also made several commits. At the end of the day we want to incorporate all changes that have been made to the trunk since we branched. This is easy! We go into the root of our branch directory and execute:

svn merge https://svn.server.com/svn/MyProject/Trunk@100 https://svn.server.com/svn/MyProject/Trunk@HEAD

Actually, there are shorter ways to write this, but lets stick to the long way for the time being and explain what the command actually does. The svn merge command needs only two parameters to indicate what changes we want. In this case we are asking svn to get all the changes that happened in trunk from revision 100 to the HEAD revision and then apply them to our current working copy.

It is important to understand that merge does not actually modify the repository at all, it simply patches our working copy with the result of diffing /Trunk@Head and /Trunk@100. Now you can take a look at the results, resolve any conflicts, make sure everything compiles fine and then commit all changes to the branch. You will probably want to add a commit message such as "merged in changes up to Trunk@####", where #### would be whatever version number your Trunk was at when you ran the merge command. Why do this? Well the next time you merge you'll only want to incorporate changes that happened to trunk since your last merge, so it's a good idea to keep track of what changes you have already merged so you don't try to merge them again.

It's a good idea to keep merging changes from trunk into your branch as often as possible, although probably not as often as you'd run an svn update under normal circumstances. Once a day should be good enough for most people, but if you start to see lots of conflicts you might want to do it more often.

Merging it all back to Trunk

So you finished your big change, everything works, and it's time to merge all your changes back to the trunk so that all your fellow developers can be amazed by how great a job you have done. Well, if you followed my advice and regularly merged changes from trunk into your branch, then this is actually a very painless task. When you think about it, you've already incorporated all the changes the other developers made in trunk into your branch, so your branch already looks like what you want the final result to be. All we have to do now is make our trunk look exactly like our branch and we are done. To do this, we should go into the directory in which we have our trunk checked out and run the following command:

svn merge https://svn.server.com/svn/MyProject/Trunk@HEAD https://svn.server.com/svn/MyProject/Branches/MyBranch@HEAD

WHAT?? I think this command needs a little explanation, but it's not hard if we understand the diff+patch concept. Basically we are asking subversion to diff our branch and the trunk and then patch these changes into Trunk (you did remember to cd to trunk's working dir right?). In other words, we are telling subversion to give us all the changes needed to get us from Trunk@HEAD to MyBranch@HEAD and then apply those changes to Trunk's working dir. If we patch Trunk with the changes necessary to go from Trunk -> MyBranch then what does Trunk end up looking like? That's right..... it should end up being exactly like MyBranch. Now all that is left to do is commit the changes  and we should have successfully accomplished a branch/merge.

Other fun uses of Merge

Once you understand that merge is simply diff+patch, you can find other creative uses. How many times have you committed something and then realized you screwed up and wished you could undo that commit? Well merge can be used to quickly undo your commit:

svn merge @HEAD @PREV
svn commit -m "Undoing my last commit"

or you might just undo one file

svn merge MyBadMistake.cs@HEAD MyBadMistake@PREV

The possibilities are endless!

Conclusion

I hope I've managed to demystify the svn merge command somewhat. If you already knew all this... well.. sorry to bore you. But if I saved at least one poor soul out there from the headaches of branching/merging the hard way, then I have accomplished what I set out to do.

by Dan on Wednesday, April 02, 2008 12:31:54 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [10]  |  Trackback
 Tuesday, April 01, 2008

Well, here I am. I'm the newest member of the Eleutian dev team. I've been settling in at Eleutian for the last couple of months and thought it'd be as good  a time as any to introduce myself and start blogging. Prior to Eleutian I worked on web applications in Java, so so I've been settling into the whole C#/.NET thing over the last few months as well. Hopefully my ramblings will be of some use to someone.

by Dan on Tuesday, April 01, 2008 10:20:08 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback