RSS 2.0
# Thursday, January 28, 2010

On my new project I want to start using end to end testing.

The idea is to write an specification run it against an outer interface. Gui, Web service, etc. It fails. So you start implementing the feature using TDD until the Spec pass.

You write a second scenario and you start again. If everything works as supposed I should have a fairly well tested application, not only at the unit level but at the integration and user acceptance level as well.

Since the application will be written in c# I look around for some tool to write the Scenarios in the same language. There are some options but none of them was as elegant as using Cucumber. So I tried cuke4nuke but I have no luck with it. I kept getting an error about server not running or something. It looks like a permission problems with win 7.

I’m sure I could have figure it out (some confidence I have on my abilities :-)) but after giving it a second though I decided to go with Cucumber and RSpec for those test. Drive the browser with Watir and hit the web services end points with webrat, sometimes even script the UI with webrat when the browser is not really need it.

Installing all the gems is easy just

gem install cucumber
gem install webrat
gem install mechanizer
gem install watir
gem install rspec 

 

and you are done (at least in my case). Of course you need to have ruby installed in your system. I have 1.8.6

Since I haven’t really used Cucumber before and my Ruby is still very flaky, I decided to use RubyMine as my IDE to write the specs, specially because you can generate the step definitions from the features in a similar way as how you generate code with R# in VS.

You start writing an Spec with one scenario like this:

ScreenShot001

Then you run it via the console and have this result.

ScreenShot008

Note the yellow squiggly lines on the step definitions for the scenario? If you move the mouse over them a prompt will indicate that the step haven’t been created yet:

ScreenShot002 

Hit Alt+Enter to see a suggested solution:

ScreenShot003

Click enter and you have some options, to use an existing step definition file or create a new. If you hit create a new one and you don’t have an step_definitions folder RubyMine will create it for you.

ScreenShot004

In this case I select the existing bing_steps.rb file

ScreenShot005

Notice that the values between quotes are replaced by a regular expression, hit tab to modify the different tokens of the method template. After generating all the methods and adding the necessary code, this is the result.

ScreenShot006

And when running via the console this is the result:

ScreenShot007

In this case we are running this specs against an existing piece of software, in my case I will run this against a new un-written site. So to see the scenario pass I should write the feature as well.

kick it on DotNetKicks.com Thursday, January 28, 2010 12:02:27 AM (Eastern Standard Time, UTC-05:00) by Hernan Garcia #    Comments [1] - Trackback
Frameworks | Methodology | Programming | Testing | Tools
# Thursday, January 21, 2010

Probably you are aware of Edgecase Ruby Koans. In case you aren’t, let me introduce you to them.

From Wikipedia, Koan:

A kōan is fundamental part of the history and lore of Zen Buddhism. It consists of a story, dialogue, question, or statement whose meaning cannot be accessed by rational thinking, yet it may be accessible by intuition. A widely known kōan is "Two hands clap and there is a sound; what is the sound of one hand?"

The Ruby Koans are a set of failing test that you need to resolve. Of course the idea is not just to resolve the test as fast as you can but to read the code carefully and understand why it’s failing and them provide the solution.

Once you download the code you just run the rake command inside the folder where the Koans have been downloaded and you will be presented with a failing test and a message in the screen that indicates what you need to do to fix the test.

You should take as much time as needed to contemplate the solution and internalize the code, the syntax and the constructs that Ruby use.

I went through them once and I’m planning on do it again in a day of two. The Koans cover some important aspect in the following areas: asserts, arrays, arrays assignments, blocks. Classes, open classes and class methods.  Inheritance, hashes, exceptions and so much more, this is the complete list of files in the Koans folder:

17/01/2010  11:25 PM             2,024 about_arrays.rb
17/01/2010  11:29 PM             1,015 about_array_assignment.rb
17/01/2010  12:27 PM               942 about_asserts.rb
18/01/2010  11:51 PM             2,392 about_blocks.rb
21/01/2010  12:02 AM             3,873 about_classes.rb
21/01/2010  06:20 AM             3,820 about_class_methods.rb
18/01/2010  12:11 AM             2,320 about_control_statements.rb
22/12/2009  10:24 PM             1,436 about_dice_project.rb
18/01/2010  12:24 AM             1,374 about_exceptions.rb
22/12/2009  10:24 PM               317 about_extra_credit.rb
17/01/2010  11:35 PM             1,765 about_hashes.rb
21/01/2010  12:07 AM             1,652 about_inheritance.rb
18/01/2010  10:10 PM             2,441 about_iteration.rb
21/01/2010  06:39 AM             4,277 about_message_passing.rb
18/01/2010  12:02 AM             3,613 about_methods.rb
21/01/2010  12:10 AM             1,132 about_modules.rb
17/01/2010  08:08 PM             1,020 about_nil.rb
21/01/2010  12:03 AM               920 about_open_classes.rb
21/12/2009  04:38 PM             3,295 about_proxy_object_project.rb
19/01/2010  12:10 AM             2,657 about_sandwich_code.rb
21/01/2010  12:15 AM             1,870 about_scope.rb
20/01/2010  11:46 PM             1,843 about_scoring_project.rb
17/01/2010  11:51 PM             4,725 about_strings.rb
22/12/2009  10:24 PM               771 about_triangle_project.rb
22/12/2009  10:24 PM               486 about_triangle_project_2.rb
18/01/2010  12:12 AM               788 about_true_and_false.rb
22/12/2009  10:24 PM             1,111 array_test.rb
21/12/2009  04:38 PM                19 code_mash.rb
21/12/2009  04:38 PM             4,498 edgecase.rb
22/12/2009  10:24 PM                15 example_file.txt
22/12/2009  10:24 PM               156 first_test.rb
22/12/2009  10:24 PM             2,323 GREED_RULES.txt
21/01/2010  06:32 AM               895 path_to_enlightenment.rb
21/12/2009  04:38 PM               159 Rakefile
02/01/2010  10:19 PM             5,482 README.rdoc
22/12/2009  10:24 PM                70 test_helper.rb
18/01/2010  12:29 AM               821 triangle.rb

 

Open your favorite editor, launch the console and start running the Koans, just type rake and you will be presented with messages like this,after fixing it your awareness will “expand”.

Thinking AboutOpenClasses
  test_as_defined_dogs_do_bark has expanded your awareness.
  test_after_reopening_dogs_can_both_wag_and_bark has damaged your karma.

You have not yet reached enlightenment ...
<"HPPY"> expected but was
<"HAPPY">.

Please meditate on the following code:
./about_open_classes.rb:26:in `test_after_reopening_dogs_can_both_wag_and_bark'
path_to_enlightenment.rb:28

 

It’s very addictive, the only complain/suggestion I have is to provide some answer to some of the question in the code. May be in a separate show?

 

    # THINK ABOUT IT:
    #
    # Is it better to use
    #    obj.nil?
    # or
    #    obj == nil
    # Why?
kick it on DotNetKicks.com Thursday, January 21, 2010 11:09:54 PM (Eastern Standard Time, UTC-05:00) by Hernan Garcia #    Comments [0] - Trackback
General | Methodology | Patterns | Programming | Testing
# Wednesday, January 20, 2010

Since I started using Git a few months ago, and particularly GitHub since last September, my life have been good in DVCS land.

I used to be a Subversion user and I was happy*, maybe because I didn’t know anything better. Of course I heard all the cool kids (specially in the Ruby world) talking about Git and bragging about it, but I was being loyal to my old pal SVN.

But this was slowing me down and I wasn’t aware of it. I’m not sure what make me install msysgit for the first time. After struggling a little bit at the beginning and wrapping my head around the concepts and the commands I noticed that my flow started to change.

This change was good. Was more Agile. Doing small commits for little changes of code seems natural since the speed of this commits was almost instantaneous (remember the commits happens in your own machine). I’m talking of commits been done almost at the line of code level.

Change this line, run the test, commit. Write another test. Make it fail. Write some code. Make it pass. Commit. Refactor. Run test. Commit. Keep going.

Once It was time to push those changes to the master a single command push every change + every comment at blasting speed.

Since them I started using Mercurial as well and the experience was very similar. In the case of Mercurial I just use TortoiseHg but I stick with the command line for Git for most of my operations and I’m glad of that decision.

I wasn’t planning on writing this post today but I just happen to grab the code for edgecase Ruby Koans from GitHub and it took me all of 1 minute to do everything. Here is the flow:

Open Console2 and launch the Git bash. Type the following sequence of commands.

Welcome to Git (version 1.6.4-preview20090730)
Run 'git help git' to display the help index.
Run 'git help <command>' to display help for specific commands.
Hernan@HERNAN-STUDIO /c/Development
$ cd Code/Ruby/Koans_unresolved/
Hernan@HERNAN-STUDIO /c/Development/Code/Ruby/Koans_unresolved
$ git pull git://github.com/edgecase/ruby_koans.git
fatal: Not a git repository (or any of the parent directories): .gi
t
Hernan@HERNAN-STUDIO /c/Development/Code/Ruby/Koans_unresolved
$ git init
Initialized empty Git repository in c:/Development/Code/Ruby/Koans_
unresolved/.git/
Hernan@HERNAN-STUDIO /c/Development/Code/Ruby/Koans_unresolved (mas
ter)
$ git help
Hernan@HERNAN-STUDIO /c/Development/Code/Ruby/Koans_unresolved (mas
ter)
$ git pull git://github.com/edgecase/ruby_koans.git
remote: Counting objects: 294, done.
remote: Compressing objects: 100% (286/286), done.
remote: Total 294 (delta 184), reused 0 (delta 0)Receiving objects:  44% (130/29Receiving objects:  45% (133/294)
Receiving objects: 100% (294/294), 51.84 KiB, done.
Resolving deltas: 100% (184/184), done.
From git://github.com/edgecase/ruby_koans
 * branch            HEAD       -> FETCH_HEAD
Hernan@HERNAN-STUDIO /c/Development/Code/Ruby/Koans_unresolved (master)
$

 

Notice that I had to type help because I didn’t remember if I had to add a remote or I was able to do a pull right away (I removed the help output from the console output fro brevity).

Of course the Ruby Koans are just a bunch of very simple text files but the whole process took me less than 2 minutes. I think that is not just because Git is faster but also using the command line for this type of task tends to be a lot faster than using a Gui tool.

If you haven’t try it yet go ahead and take the plunge. Go distributed, even if you work alone, you want regret it.

*I’m still using Subversion at work, looking forward to have the time to switch but we are dealing with some time sensitive projects so I don’t want to mess around with that.

kick it on DotNetKicks.com Wednesday, January 20, 2010 12:42:31 AM (Eastern Standard Time, UTC-05:00) by Hernan Garcia #    Comments [0] - Trackback
Continuous Integration | Methodology | Programming | Tools
# Monday, January 18, 2010

In case you don’t know what it is. Codemash is a conference put together by volunteers. It has been running for four years now. The conference happens at the Kalahari Resorts and Convention Center that has reportedly the biggest indoor water park in North America. That is in Sandusky, Ohio.

Organization

I only have one world for it, spectacular. You come in and once you register you get your welcome package, a tag and a marker to write down your name, nickname, handler or however you want to be identified. (I saw one tag that only have a big E in it. And that is cool). A lot of attendees (me included) choose to add their twitter handle. If you think about it, at the end of the day a lot of us talk to each other or read each other on twitter so that makes sense. After that your only problem in the world is try to get to as many sessions or open spaces as possible.

Content

Multiple technologies and practices are been represented at Codemash. Ruby, Java and JVM languages, .NET and CLR/DLR languages, Python, Iron*, C. Functional and OO. SOLID, BDD, TDD, Lean, Leadership, Coaching, Patterns. Iphone, Rails, WebForms, Silverlight, WPF, Tapestry and more development platforms, etc. And if you can’t find what you want, you still have the open spaces, so go ahead and create your own conference. I bet people will join you.

There is content at the Beginner, Intermediate and Advanced levels. I could like to see a few more 400 level talks but if you think that the idea of the conference is to try to get you out of your comfort zone that may not be very wise. Let me explain.

The idea is to try to go to talks that are not about the same technologies that you use every day. For example I choose to attend some F#, Ruby, Python and Clojure talks. My level of familiarity varies so I was able to follow and take some good information from the sessions since they were at the intermediate/beginner level.

Sessions and open spaces I enjoyed.

The keynotes by Mary Poppendieck’s The Five Habits of Succesful Lean Development and Andy Hunt’s The Mother of all Bugs

Some of the sessions/Open spaces: Presentation Patterns. What makes ruby different. Open space about FubuMVC. NoSQL: Death to relational DB’s. Introduction to Cucumber. Testing ASP.NET applications using Ruby. Being and evil genius with F#. 0-60 with Fluent NHibernate. Building webapps with Compojure. IronPython with ASP.NET.

The venue

Perfect. I think that the venue is part of the magic that make this Conference so special. Imagine that you are in this African themed hotel, where people wearing sandals and T-shirts around you will be checking their emails or updating their twitter timeline from their smart phones. Imagine going to a water park after the last session of the day, or just go and play mini golf with your son. That makes for a very relaxed vibe and you feel it and see it at the conference.

The staff at the hotel is great, friendly and professional and all interaction (from the moment I made my reservation on the phone) was very pleasant.

The food

Ok. This is something I’m really surprised. You pay $175 for the 2 days of conference + $150 for the extra Precompiler day. That’s a grand total of $325  for a 3 day conference. So, you may expect to have some scarcity on the food supply, specially when you consider that you have breakfast and lunch all of three days and dinner on one of the days.

Well, let me tell you something. There was not such thing. The food was good and plentiful. Actually It was fantastic. I went to conferences where I paid $2000 for the same number of days and all I got was a wrap or a sandwich that was prepared 12 hours before.

On top of that there was coffee and pops (coke and sprite cans) available during the day to keep you going.

What I will change

Nothing from the conference, maybe extended to 3+1 days?

My recommendations for new attendants.

If you have a family take them with you, specially if you have kids. My only mistake (and seems to be a common theme among first timers) was to go along. The organization even has a KidsMash going on where the kids can play and be ask geeks as their parents when they are tired of the water park.

Try to study the list of sessions in advance but relax and make sure you scan the Open spaces regularly and keep an eye on that twitter timeline. If you are not getting the most of the session you are in move to another one, just try not to disrupt

And like in most conferences take a power cord (a long one if possible) with you.

I’m already impatiently waiting for next year Codemash. I can only say a big thank you to all the people that works to make such a great experienced for all of us.

kick it on DotNetKicks.com Monday, January 18, 2010 11:16:28 PM (Eastern Standard Time, UTC-05:00) by Hernan Garcia #    Comments [1] - Trackback
General
# Friday, January 01, 2010

Kazi Manzur Rashid has a post about registering Areas dynamically after the registration of other routes and the problems this has since the order the routes are registered is very important. Go read his post and come back for a possible solution to the problem.

Ok, based on his post I decided to try to implement exactly what he is looking for. After poking around with reflector and brushing up my Reflection skills I came up with a first implementation that does the trick.

  1:     public static class RoutCollectionExtension
  2:     {
  3:         public static RouteCollection AddArea(this RouteCollection routes, string routeName, Route newRoute)
  4:         {
  5:             var fieldInfo =  routes.GetType()
  6:                 .GetField("_namedMap", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  7: 
  8:             var dict = fieldInfo.GetValue(routes);
  9:             dict.GetType()
 10:                 .GetMethod("Add", BindingFlags.Public | BindingFlags.Instance)
 11:                 .Invoke(dict,new object[]{routeName,newRoute});
 12: 
 13:             fieldInfo.SetValue(routes,dict);
 14: 
 15:             routes.GetType()
 16:                 .GetMethod("InsertItem", BindingFlags.NonPublic | BindingFlags.Instance)
 17:                 .Invoke(routes, new object[] { 0, newRoute });
 18: 
 19:             return routes;
 20:         }
 21:     }

After posted this solution as a comment on Kazi’s post I decided to polish this a little more and to actually provide a similar API as the MapRoute extension from the MVC framework. The idea is to provide a set of InsertRoute and InsertRouteAfter.

So for the InsertRoute, this is the final code:

  1:     public static class RoutCollectionExtension
  2:     {
  3:         public static void InsertRoute(this RouteCollection routes, int index, string routeName, Route newRoute)
  4:         {
  5:             var fieldInfo =  routes.GetType()
  6:                 .GetField("_namedMap", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  7: 
  8:             var dict = fieldInfo.GetValue(routes);
  9:             dict.GetType()
 10:                 .GetMethod("Add", BindingFlags.Public | BindingFlags.Instance)
 11:                 .Invoke(dict,new object[]{routeName,newRoute});
 12: 
 13:             fieldInfo.SetValue(routes,dict);
 14: 
 15:             routes.GetType()
 16:                 .GetMethod("InsertItem", BindingFlags.NonPublic | BindingFlags.Instance)
 17:                 .Invoke(routes, new object[] { index, newRoute });
 18:         }
 19: 
 20: 
 21:         public static Route InsertRoute(this RouteCollection routes, int index, string name, string url)
 22:         {
 23:             return routes.InsertRoute(index, name, url, null, null);
 24:         }
 25: 
 26:         public static Route InsertRoute(this RouteCollection routes, int index, string name, string url, object defaults)
 27:         {
 28:             return routes.InsertRoute(index, name, url, defaults, null);
 29:         }
 30: 
 31:         public static Route InsertRoute(this RouteCollection routes, int index, string name, string url, string[] namespaces)
 32:         {
 33:             return routes.InsertRoute(index, name, url, null, null, namespaces);
 34:         }
 35: 

36: public static Route InsertRoute(this RouteCollection routes, int index, string name, string url,

object defaults, object constraints)

 37:         {
 38:             return routes.InsertRoute(index, name, url, defaults, constraints, null);
 39:         }
 40: 

41: public static Route InsertRoute(this RouteCollection routes, int index, string name, string url,

object defaults, string[] namespaces)

 42:         {
 43:             return routes.InsertRoute(index, name, url, defaults, null, namespaces);
 44:         }
 45: 

46: public static Route InsertRoute(this RouteCollection routes, int index, string name, string url, object defaults,

object constraints, string[] namespaces)

 47:         {
 48:             if (routes == null)
 49:             {
 50:                 throw new ArgumentNullException("routes");
 51:             }
 52:             if (url == null)
 53:             {
 54:                 throw new ArgumentNullException("url");
 55:             }
 56:             var item = new Route(url, new MvcRouteHandler())
 57:                              {
 58:                                  Defaults = new RouteValueDictionary(defaults),
 59:                                  Constraints = new RouteValueDictionary(constraints),
 60:                                  DataTokens = new RouteValueDictionary()
 61:                              };
 62:             if ((namespaces != null) && (namespaces.Length > 0))
 63:             {
 64:                 item.DataTokens["Namespaces"] = namespaces;
 65:             }
 66:             routes.InsertRoute(index, name, item);
 67:             return item;
 68:         }
 69:     }

The problem with this is that you probably don’t know the index of the routes and those index will change with each route that get’s registered. So InsertRouteAfter is better since we can insert a route after another route by name. The code is very simple, I won’t display all the overloads just the actual implementation.

  1:         public static void InsertRouteAfter(this RouteCollection routes, string nameOfExistingRoute, string nameOfRouteToInsert, Route newRoute)
  2:         {
  3:             var fieldInfo = routes.GetType()
  4:                 .GetField("_namedMap", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  5: 
  6:             var dict = fieldInfo.GetValue(routes);
  7:             dict.GetType()
  8:                 .GetMethod("Add", BindingFlags.Public | BindingFlags.Instance)
  9:                 .Invoke(dict, new object[] { nameOfRouteToInsert, newRoute });
 10: 
 11:             var existingRoute = dict.GetType()
 12:                 .GetProperty("Item")
 13:                 .GetValue(dict, new[] {nameOfExistingRoute});
 14: 
 15:             fieldInfo.SetValue(routes, dict);
 16: 
 17:             var index = routes.GetType()
 18:                 .GetMethod("IndexOf", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
 19:                 .Invoke(routes, new[] {existingRoute});
 20: 
 21:             index = (int) index + 1;
 22: 
 23:             routes.GetType()
 24:                 .GetMethod("InsertItem", BindingFlags.NonPublic | BindingFlags.Instance)
 25:                 .Invoke(routes, new[] { index, newRoute });
 26:         }
Warning!!!

If you decide to use this code make sure that you have tests in place since we are relying in things like the name of a internal field that can be changed without affecting the public API so this extensions are fragile from that point of view. Besides that, reflection is slow, but since route registration should happens only once per application I’m not worry about that part.

 

Shout it
kick it on DotNetKicks.com Friday, January 01, 2010 10:47:18 PM (Eastern Standard Time, UTC-05:00) by Hernan Garcia #    Comments [0] - Trackback
Programming
# Saturday, December 26, 2009

When the Codemash guys announced their API I decided to create an app using it. I wasn’t sure what to do at first but It was pretty obvious anyway. Some kind of scheduling tool.

It took me some time to have the time to start and them to finish it. I finally was able to deploy this last night and today I add another feature to considered completed based on my initial goal.

You can visit the tool here: http://mysessioncalendar.com/ 

What it does?

The tool has three tabs one for each conference day and a third for the pre compiler. Each tab has columns (representing the rooms where the sessions take place, just noticed I don’t have the room on top) and them the sessions are displayed below ordered by time.

The idea is that you can select the sessions you are interested in. The tool does not make any judgement calls and if you want to select two sessions in the same time slot is up to you. Once you mark all the sessions just click the “Save Schedule” button on top and a modal dialog will display with a link to open (in a new window) a list with the selected sessions.

This time the sessions are ordered in three columns: One for each day and the sessions for each day are ordered by time.

The page has the AddThis widget that allow you to twit, email, print, add to favourites, show them in facebook and more. Another cool option is to export them as iCal
, this way you can add them to your google calendar and other tools supporting this format.

How was done.

The site have been implemented using ASP.NET MVC, jquery for all the JavaScript and the UI design using JQueryUI. Data is saved as xml so no need to use databases. Originally I started using Castle.ActiveRecord since the data model is extremely simple, but is so simple that the use of a db was overkill. The total time to have the site done was maybe 24 man hours divided in several coding sessions of no more than 3 hours at a time.

The use a a widget like AddThis make implementing the sharing functionality a 15 minutes deal.

Conclusion.

There are some things that can be better like font sizes (thanks Ahmed for the report). Originally I wanted to have a better interface with drag and drop or double click in a session to select, but decided to go with a simpler implementation and get this out of my computer and into the wild.

kick it on DotNetKicks.com Saturday, December 26, 2009 10:10:11 PM (Eastern Standard Time, UTC-05:00) by Hernan Garcia #    Comments [1] - Trackback
General
# Sunday, November 22, 2009

Some time ago I wrote a first impressions about ASP.NET MVC in Action from Manning. It was after downloading an reading a few chapters available via the Manning early access program (MEAP). The book was written by Jeffrey Palermo, Ben Scheirman and Jimmy Bogard.

A month ago or so I finally got my print copy and I started reading it right away. Let me put it simple, this book is fantastic. If you are planning to do any development with the framework you need to have it in your book shelves.

The content span over just 352 pages and it covers pretty much every single aspect of the framework. It follows a very clear path explaining how the pieces fit together. I think that It can be useful for both the experienced and the novice programmer.

One of the remarkable aspects of the book is the constant focus on testability and customization of the different pieces of the framework to help you reduce friction and improve the design of your application.

I also felt that the authors took a very pragmatic approach while exposing users to different options on implementing web applications with the framework.

I can see the book as having 3 parts. The first 6 chapters explain and show how to use and extend the framework. Chapters 7 to 10, explore more complex scenarios, like complex sites, use of AJAX, how to leverage existing asp.net features and hosting/deploying your final app.

The last part is a compendium of Best practices, Recipes and an study or other two MVC frameworks, Monorails and Ruby on Rails.

kick it on DotNetKicks.com Sunday, November 22, 2009 5:25:43 PM (Eastern Standard Time, UTC-05:00) by Hernan Garcia #    Comments [2] - Trackback
Books
# Monday, November 16, 2009

I try to be pragmatic in my approach to development and one of the things that change the most are the tools I use to deliver software. There are several reasons why I change tools so often.

  1. The evolution of the software I write call for new or different tools.
  2. Search for efficiency and eliminate pain points.
  3. I change my approach to software development and new methodologies need new tools.
  4. I just love to try new stuff :-)

In this post I want to concentrate in the tools used to manage projects and builds. Until recently my favoured tools in this context consisted of NAnt, CC.Net/Hudson and Subversion.

For bug tracking I used the bug tracker in Google code for my OSS projects integrated to TortoiseSVN or BugTracker.Net. (Note: At work we use FogBugz and we are very happy with it.)

Subversion was the first to go.

Subversion is a great VCS but I usually have two problems with it. Speed and problems with complex merges.

When I work alone, merges are not an issue of course, but speed still is. At the same time more and more people seems to be switching to DVCS (Distributed or Decentralized) systems like Git or Mercurial. After taking a quick look at GitHub and follow their tutorials I was able to move some of my projects there in a few hours. (Most of the time spent on reading and learning from other people mistakes).

Git is fast, Fast, FAST! The whole idea of local commits and clone repositories is fantastic and they really help me with my workflow in the sense that I can do one or two changes, commit, one or two more, commit, find a bug, revert change, finish a story, push to GitHub.

To manage Git I’m using a combination of command line and graphic interface using Git gui. So far I haven’t feel the need to use/install TortoiseGit.

I still have some projects hosted in google code and I’m using Subversion with them, I’m thinking on switch them over to GitHub once I start working on them again.

Nant followed it.

I don’t have a problem with XML so the fact that Nant is XML based does not bothers me, really. But I also like the power of a good scripting language to manage repetitive tasks. I decided to move away from Nant and try to adopt some of the newest build systems.

I took a look at psake and them I read “How a net developer learned ruby and rake to build net apps in windows” by Derrick Bailey and that convinced me to take the plunge.

My knowledge of Ruby is extremely rudimentary but I even with that handicap I was able to have a Rake build script up and running in less than 90 minutes. This script cleans the build target, create the Package folder, builds the VS solution, run Nunit test on two dll's, generate the NUnit report as an xml file, and run the migrations from Migrator.Net (that last part is not working yet, I will need to take a closer look at Migrator.Net command line args).

The most useful resource on Derik's post was Laribee's OMG Rake!. Laribee’s sample code and a few queries to Google was all I need. (No, I did not copy and paste ALL Laribee’s code, just use it as a reference)

Agile Zen or project management made easy.

I got a free account on Agile Zen the first week after they went live. I remember creating the account, playing around on the Board and leaving the site. My thoughts at the moment were something like. This is actually cool. Very nice design. Good usability. I should give it a proper test drive with some real project.

Of course, I never came back until last Friday. While working in a few features for Pronghorn I decided that it was time I stop spiking and started to write proper user stories to drive the framework. I remembered Agile Zen and went back.

The site looks great and there are some improvements since that last time I saw it.

What really amazed me is how intuitive the whole process is. There is no waste generated by using this tool. Creating stories is 1 click. Editing stories, another one. Color coding two clicks. Double click in a field to edit them, etc. Very easy, very intuitive. There is even a bar at the bottom with hints that I decided to hide and I didn’t miss it.

The site is very responsive and the only thing I miss is integration with a VCS system. They have a very simple API for paying accounts, but in the docs it looks like is read only, so no hooks in there (If anybody knows otherwise, please leave a comment).

I will keep using it for another week or so before making a final decision but so far everything indicates that I will be upgrading the account to a paying one pretty soon. (The free account only allows for one project and one developers, what is more than fair.)

Tying it up all together with CI.

As I mentioned before my main experience have been using CruiseControl.Net and Hudson as the CI servers. I installed TeamCity a long time ago to give it a try but I never use it. My first choice was to look for some hosted solution. After searching I only found a few and non of them worked with .Net (at least not at the moment).

I was going to go back once more with Hudson but I wasn’t able to connect to the Hudson site to download the code. (Their site is up now). So I decided to take a new look at JetBrain’s TeamCity. At the moment of this writing they are running the EAP for version 5.

I wanted to install it and use my newly crafted Rake build script with the .Net project and have my test report integrated in the dashboard.

First I got the msi from the daily builds for version 5.00. Double click on it to install the server and the agent and after a few minutes and two (three?) questions, the home page of the serve shows up in the browser.

Creating the first project and associated build profile was a breeze. I just followed along the instructions in the screen. A few times when I wasn’t sure what a given label meant, I made use of the contextual help.

I did have an issue but it was my fault when setting some relative path to the build file and the build target, for running test and creating the Package folder.

From downloading the installer to having the project building successfully took me between 10 to 15 minutes.

Conclusion.

This new setup makes me more productive since I have better tools that save me time in different areas like. Setting things up, working around their idiosyncrasies, configuration heavy or too verbose a language.

While this is a combination that works for me, yours may be completely different. The important part is to have tools that feel this roles and make sure that they are really working with and for you and not the other way around.

kick it on DotNetKicks.com Monday, November 16, 2009 12:26:55 AM (Eastern Standard Time, UTC-05:00) by Hernan Garcia #    Comments [1] - Trackback
Continuous Integration | Methodology | Programming | Testing | Tools
Add The Dynamic Programmer Mippin widget
Navigation
Archive
<February 2010>
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213
What I'm reading
Shelfari: Book reviews on your book blog
About the author/Disclaimer
Hernan Garcia I have been a software developer for the last 16 years or so.
I was a journalist before and I still consider myself one.
Besides baseball, programming is my other big passion.

Me on twitter. @TheProgrammer
Certified Scrum Master
© Copyright 2010
Hernan Garcia
Sign In
Statistics
Total Posts: 197
This Year: 15
This Month: 1
This Week: 0
Comments: 70
Themes
Pick a theme:
All Content © 2010, Hernan Garcia