Sunday, August 15, 2010

Git Saved my @$$: Episode I–The Phantom Branch

I have been enjoying Git for a while now.  Since switching to Git on my current project, we have been quietly succeeding.  However, whether through disinterest, or laziness, I avoided really understanding how it worked.  That is, until it saved my ass.

So here’s the deal.  I was on a tear.  I just finished coding and testing a feature.  As I am now wont to do, I was working on a local feature branch (PO-updates).  It was time to merge back to our development branch.  Actually, it was time to rebase, but I merged out of ignorance.  There were merge conflicts in the project (*.proj) file, but I was on fire.  Not time to pay attention to the output.  I ran all my unit tests, and [blam] green bar!  Ok, merge complete (or so I thought).  Time to delete the feature branch.

Screenshot of me not noticing the warning "error: the branch 'PO-updates' is not fully merged. If you are sure you want to delete it, run 'git branch -D PO-updates", and me (of course) running "git branch -D PO-updates"

Oh crap!  After the initial freaking out was over, I took a deep breath and reviewed what I knew about Git (which was very little).  Well, as it so happens, I was working in the same session where I did the final commit for that branch.  The command “ci” is just a shell script that adds new files then commits changes.

A screenshot of my last commit (with comment "finished").  It shows that the ID for the branch "PO-updates" is 1c5680b.

Hm, I wonder what I can do with this information.  The ID of the branch PO-updates is 1c5680b.  Maybe lets see if I can see the log just for this branch.

"git log 1c5680b" yields the id of the commit "finished"

Holy $#!+ that worked!!  Now I have this big long @$$ commit ID (c15680b2647bfcb02d7ed6723a30d9fe2cd62e7 for anyone who cares).  After pondering what I could do with that for a while, I formulated this hypothesis.  Git seems to let you do just about anything.  I wondered if it would let me merge that merge the last commit in to a new branch.

Creating a new branch.  "git co -b PO-changes-deux" then merging changes from the big honking ID for the last commit.

Double holy $#!+ b@man! I think it just did something amazing.  Did it really just merge a commit from a deleted branch into a new branch?  Is it possible that it would be cool enough to not immediately purge the deleted files from history?  I nervously opened up my project.  In truth, Git had me at “git init,” but that was the very moment where I became a sincere Git fanboy.  I don’t enter into fandom lightly, since I tend to think of fanboys as mindless zombies, but this was too much.  I LOVE GIT!

All that I had left to do was to rename the branch to the proper name.

git branch -m PO-changes-deux PO-changes

Now I no longer delete feature branches when I’m done with them.  I created a shell script called “archive” that surrounds the branch name in parentheses.  “archive PO-changes” would have changed the branches name to “(PO-changes)”.  I also created a shell script called “shelve” which surrounds the branch name in curly braces.  This allows me to organize the branches and visually differentiate active and inactive branches.  Shelved branches show up at the bottom of a branch list, and archived branches show up at the top.

image

Monday, April 12, 2010

Debug NUnit tests in Visual Studio

While developing the NUnit addin for Lingual, I had to come to terms with something painful.  If I use Lingual for my tests, I lose Resharper support for running unit tests in Visual Studio.  While this tradeoff isn’t bad (the NUnit GUI works fine), it also means I lose debugging support, which can be painful.

If you do BDD right, you find that you don’t need to debug often, but you still do need debugging for those particularly pesky bugs.  Not being able to debug my tests was a nonstarter.  Luckily, I found some tidbits on the internets that led me to the light.  Unfortunately, there’s no “tutorial” style page out there that I thought good enough to link to, so here goes.

In order to debug NUnit tests in Visual Studio, you need to start the NUnit GUI as an external program from Visual Studio.  As best I can determine, this will start NUnit and immediately attach to the process on which it runs.

First, if you don’t already have an NUnit project (*.nunit), open the NUnit GUI and create a new project.  Add your test projects to this.  Save it under your solution directory.

image

Next, in visual studio, in the project properties of your test project, under the “Debug” tab, click the “Start External Program” radio button.  Point it to the location of your NUnit GUI.  Under “Command line arguments” put the path to your nunit project file.

image

Now, you can right click on the project and choose Debug > Start new instance.  This will open the NUnit GUI.  Now, if you run a test that has a breakpoint set, Visual Studio will hit that breakpoint as normal.

image

Alternately, you could set the test project as your startup project.  Do this by right clicking the project and selecting Set as StartUp Project.  Now whenever you run by F5, or Ctrl-F5, the NUnit GUI will start..

image

There are still some pain points, like with Resharper, you could double click on a test, and it would take you to the method, or double click on a test fixture, and it would take you to the class.  Also, I’ll miss the hyperlinks on the stack trace that take you to the code location.  My hope is, though, that the gains in having an expressive language based testing framework will offset the losses in giving up Reshaprer’s integrated testing.

Sunday, April 11, 2010

Lingual, a language driven test framework

I recently drafted a syntax that I thought would be helpful for BDD style unit tests in .Net for NUnit.  I spent the last two weeks ignoring my family whenever I could to kick out something usable.  I’ll blog about lessons learned in trying to extend NUnit later (more frameworks are to follow).  This blog post is intended to explain the fluent BDD implementation.

The idea started with a question; is this possible?

It didn’t take long before I got an answer to my question.  It wasn’t exactly how I envisioned using the syntax, however, so I went ahead and continued with my effort.  My goals were as follows:

  1. It is testing framework agnostic.  This means that once the tests are developed, they can potentially be run on any testing framework (although I have only done NUnit so far)
  2. It should itself be extensible, allowing anyone to take advantage of test framework extensions, but not locking the consumers into a particular fluent language.
  3. It should be easy to use and understand.
  4. It should not be prescriptive, meaning that it should not require the consumers to change any other aspect of their development to accommodate the framework.

I think in the first version I have gotten pretty close.  I made a lot of compromises to get it working with NUnit, but they’re all under the hood.  I think that over time I can clean up the ugliness and hopefully improve performance to boot.

One thing to note (a bit of hypocrisy on my part) is that I didn’t write unit tests when developing this framework.  My next step is to test after.  It’s not TDD, but the API changed so many times between inception and completion, that TDD was very difficult.

You can get the source, or binaries on github.

The completed version has a syntax that looks like this:

image

The NUnit output looks like this:

image

I’ll break it down:

  • Given is a static class.  You can call “a” or “an” and pass it a generic parameter.  This generic parameter represents your context.  The context is the variables that are needed by your arrange and act methods.  Typically, you would include these as instance members in your test class, but since these tests run anonymously, you instead keep it in the context classes.  I found as I used this method more, I started to like it.  I’ll leave it for you to judge.
  • Once you specify the context, you can call “that”, “which”, and “but” in any order.  All of them take a params array of Action<T> delegates where T is the context class you specified in the Given.
  • When takes a Func<TContext, TResult> delegate, where TContext is the context defined above, and TResult is the class to  evaluate in your assertions.
  • After you specify your when, you can call “then” or “should” or both any number of times.  Either method takes a params array of Action<T> delegates where T is TResult from above.
  • Your specification should be in a property that returns an ITestSource
  • All of the delegates used in this syntax should be method calls, where the method’s name is the text that describes what is being done.  Use underscores instead of spaces.  When the tests are generated, spaces will be substituted for the underscores.

In your project, you only have to reference Lingual.dll, and you’re ready to roll.

To get this working in NUnit, take the following files and copy them to the appropriate NUnit addin directory.

  • Lingual.dll
  • Lingual.Proxy.dll
  • Lingual.Extensions.NUnit.dll

Which NUnit directory to copy these to is a little tricky.  Most documentation on the internets would lead you to believe that you should copy it to the bin/addins folder.  I suspect that is is only true for NUnit 2.4.x.  I’m using NUnit 2.5.4, and I had to put it under the bin/net-2.0/addins directory.  Use whichever works for you.

If you’re currently using TestDriven, or Resharper to run your NUnit tests, you won’t be able to take advantage of the integrated features.  You can, however, launch the NUnit GUI and debug your tests in Visual Studio using this method.

Stay tuned, because I’ll blog about extending Lingual next.

Please let me know what you think.  What works, what doesn’t work, and what can be improved.  In fact, feel free to extend or add as you please.  I did this because I thought it would make the world a better place, not because I wanted something that is exclusively mine.  Let’s make it ours.