<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8588149298977634954</id><updated>2011-10-04T23:16:17.115+01:00</updated><category term='NUnit'/><category term='A Bit Of Fun'/><category term='TDD'/><category term='MVC'/><category term='Google Code'/><category term='ActiveRecord'/><category term='Software Development'/><category term='SVNX'/><category term='Hardware'/><category term='TCP/IP'/><category term='SVN'/><category term='Networks'/><category term='.NET'/><title type='text'>80% Complete</title><subtitle type='html'>If you believe, you can achieve. Innit.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-5498427039865209746</id><published>2010-12-31T11:32:00.004Z</published><updated>2010-12-31T11:41:48.050Z</updated><title type='text'>WCF fully qualified type gotcha</title><content type='html'>It got me again, so I'm blogging it in the hope that I remember next time!  When specifying fully qualified type names in .NET configuration files make sure to put a space after the comma that separates the parts(highlighted in yellow below).&lt;br /&gt;&lt;code&gt;&lt;pre&gt;   &lt;br /&gt;&amp;lt;extensions&gt;&lt;br /&gt; &amp;lt;behaviorExtensions&gt;&lt;br /&gt;       &amp;lt;add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement,&lt;span style="background:yellow"&gt; &lt;/span&gt;Microsoft.IdentityModel,&lt;span style="background:yellow"&gt; &lt;/span&gt;Version=3.5.0.0,&lt;span style="background:yellow"&gt; &lt;/span&gt;Culture=neutral,&lt;span style="background:yellow"&gt; &lt;/span&gt;PublicKeyToken=31bf3856ad364e35"/&gt;&lt;br /&gt;     &amp;lt;/behaviorExtensions&gt;&lt;br /&gt;   &amp;lt;/extensions&gt;&lt;br /&gt;&amp;lt;/pre&gt;&amp;lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-5498427039865209746?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/5498427039865209746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2010/12/wcf-fully-qualified-type-gotcha.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/5498427039865209746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/5498427039865209746'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2010/12/wcf-fully-qualified-type-gotcha.html' title='WCF fully qualified type gotcha'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-2333186881668894092</id><published>2010-10-21T19:50:00.003+01:00</published><updated>2010-10-21T20:09:45.276+01:00</updated><title type='text'>Ruby on Rails : uninitialized constant Test::Unit::TestSuite</title><content type='html'>I'm working on a side-project to learn how to work Ruby on Rails using the &lt;a href="http://railstutorial.org/"&gt;tutorial&lt;/a&gt;  written by &lt;a href="http://www.michaelhartl.com/"&gt;Michael Hartl&lt;/a&gt; to guide me. I think it is an excellent reference and would thoroughly recommend it.  Anyway, the reason for this post is to supply the fix for a problem that held me up for a while in the hope that it might save someone else some pain.  For reasons too laborious to go into I ended up with the following error when trying to run my RSpec tests after upgrading to Ruby 1.9.2.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/Users/gbarrs/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:440:in `rescue in load_missing_constant': uninitialized constant Test::Unit::TestSuite (NameError)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The fix in my case was to add the the following 'require' statement to the rb spec file causing the error.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;require 'test/unit/testsuite' &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I have no idea why this line was required when the tests had been working perfectly well before the upgrade without it.  I suspect some dependency versioning issue but I can't be sure. Anyway, the fix worked for me and it may work for you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-2333186881668894092?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/2333186881668894092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2010/10/ruby-on-rails-uninitialized-constant.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/2333186881668894092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/2333186881668894092'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2010/10/ruby-on-rails-uninitialized-constant.html' title='Ruby on Rails : uninitialized constant Test::Unit::TestSuite'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-8964015251685126477</id><published>2010-07-21T21:37:00.001+01:00</published><updated>2010-07-21T21:37:49.073+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>HTTP Modules In IIS 7</title><content type='html'>&lt;p&gt;The entry for adding a HTTP Module in web.config has changed in IIS7.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Prior to IIS 7 a web config entry might look like&lt;/p&gt;&lt;code&gt;&amp;lt;system.web&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;httpModules&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;add name="startupModule" type="My.SuperHttpModule, My" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/httpModules&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/system.web&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;When using IIS 7 the entry moves from &lt;code&gt;system.web&lt;/code&gt; to &lt;code&gt;system.webServer&lt;/code&gt; and its name changes from &lt;code&gt;httpModules&lt;/code&gt; to &lt;code&gt;modules&lt;/code&gt;. A web .config entry might now look like&lt;/p&gt;&lt;code&gt;&amp;lt;system.webServer&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;modules runAllManagedModulesForAllRequests="true"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;add name="startupModule" type="My.SuperHttpModule, My" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/modules&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/system.webServer&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-8964015251685126477?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/8964015251685126477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2010/07/http-modules-in-iis-7.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/8964015251685126477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/8964015251685126477'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2010/07/http-modules-in-iis-7.html' title='HTTP Modules In IIS 7'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-1185093851326711600</id><published>2010-06-04T09:33:00.003+01:00</published><updated>2010-06-04T09:36:14.367+01:00</updated><title type='text'>The Arrangement Of Tests</title><content type='html'>I just read a post by Uncle Bob on &lt;a href="http://stackoverflow.com/questions/2965483/unit-tests-the-benefit-from-unit-tests-with-contract-changes/2969379#2969379"&gt;Stack Overflow&lt;/a&gt; and wanted to remember a section on the arrangement of tests. So I posted it here.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; border-collapse: collapse; font-size: 14px; line-height: 18px; "&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; clear: both; word-wrap: break-word; background-position: initial initial; background-repeat: initial initial; "&gt;Tests should be arranged as follows:&lt;/p&gt;&lt;ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 30px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; list-style-type: disc; list-style-position: initial; list-style-image: initial; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; background-position: initial initial; background-repeat: initial initial; "&gt;Unit tests provide close to 100% code coverage. They test independent units. They are written by programmers using the programming language of the system.&lt;/li&gt;&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; background-position: initial initial; background-repeat: initial initial; "&gt;Component tests cover ~50% of the system. They are written by business analysts and QA. They are written in a language like FitNesse, Selenium, Cucumber, etc. They test whole components, not individual units. They test primarily happy path cases and some highly visible unhappy path cases.&lt;/li&gt;&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; background-position: initial initial; background-repeat: initial initial; "&gt;Integration tests cover ~20% of the system. They tests small assemblies of components as opposed to the whole system. Also written in FitNesse/Selenium/Cucumber etc. Written by architects.&lt;/li&gt;&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; background-position: initial initial; background-repeat: initial initial; "&gt;System tests cover ~10% of the system. They test the whole system integrated together. Again they are written in FitNesse/Selenium/Cucumber etc. Written by architects.&lt;/li&gt;&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; background-position: initial initial; background-repeat: initial initial; "&gt;Exploratory manual tests. (See James Bach) These tests are manual but not scripted. They employ human ingenuity and creativity.&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-1185093851326711600?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/1185093851326711600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2010/06/arrangement-of-tests.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/1185093851326711600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/1185093851326711600'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2010/06/arrangement-of-tests.html' title='The Arrangement Of Tests'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-5794764402089556914</id><published>2010-02-25T08:04:00.001Z</published><updated>2010-02-25T08:04:58.852Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>Lessons learned from NHProf</title><content type='html'>&lt;p&gt;I went to another &lt;a href="http://skillsmatter.com/" title="Skillsmatter"&gt;Skillsmatter&lt;/a&gt; event last night where &lt;a href="http://ayende.com/blog/" title="Ayende"&gt;Ayende&lt;/a&gt; was taking about some of the lessons learned from building NHProf. The points that stuck in my mind were:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;* Every build goes straight to release&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;* Sometimes Not Invented Here is fine.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This led me to think about some other things:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;* Think about the application you are building. If it's not an enterprise application the do you really need to apply enterprise patterns. I'm not saying "don't". I'm just saying think about what is appropriate for your situation.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;* Ayende built his own build server. Is it appropriate for you to do the same? It depends :-) The reason that many people use things like Cruise Control, Team City etc is because they are well known tools. In companies where employees come and go the use of these standard tools means that new employees already know how these things work and can concentrate on learning the business stuff rather than the supporting infrastructure.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;As an aside, Skillsmatter are doing a special rate of £75 until Sunday 28th Feb for their 3 day tutorials event. I attended this last year and I thought it provided good value for money. See &lt;a href="http://skillsmatter.com/event/open-source-dot-net/progressive-dotnet-tutorials-2010ls-2010" title="their site"&gt;their site&lt;/a&gt; for details.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-5794764402089556914?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/5794764402089556914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2010/02/lessons-learned-form-nhprof.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/5794764402089556914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/5794764402089556914'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2010/02/lessons-learned-form-nhprof.html' title='Lessons learned from NHProf'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-4115562864888073501</id><published>2009-07-30T13:04:00.006+01:00</published><updated>2009-07-30T13:22:35.570+01:00</updated><title type='text'>Report Viewer Fun And Games</title><content type='html'>I had my first foray into the Report Viewer control today.  It's been a couple of hours worth of fun :-) The point of this post is to share the resolution to the two problems that wasted the most of my time.&lt;br /&gt;&lt;br /&gt;1)An object data source may not appear in the Website Data Sources window when you try to set the object data source for a SQL Server 2005 Reporting Services report in Visual Studio 2005. I couldn't understand why the buttons in the Website Data Sources window were greyed out.  It turns out to be a known bug and the hot-fix for it is at &lt;a href="http://support.microsoft.com/kb/939768"&gt;http://support.microsoft.com/kb/939768&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2) The 'XXX' parameter is missing a value : There are loads of posts for this and none of the posts I read supplied the resolution that fixed my particular problem.  I was trying to set the parameter of a local report in the page load handler. When I views the page I kept getting the error message.  When I tried to set a breakpoint, the code was not being hit, which lead me to believe that something fundamental was happening way earlier in the process.  I reasoned that there was a null check being carried out and failing the code before my code to set the parameter was being called. I wondered if there was any way to allow nulls, and there was (is).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_i8oXuszBfQ0/SnGP2mRzh1I/AAAAAAAAAAw/vhmFH8bcpv8/s1600-h/AllowNull.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 248px;" src="http://1.bp.blogspot.com/_i8oXuszBfQ0/SnGP2mRzh1I/AAAAAAAAAAw/vhmFH8bcpv8/s320/AllowNull.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5364226799325906770" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the Report Parameters dialogue box there is a Check box labelled &lt;span style="font-weight:bold;"&gt;Allow null value&lt;/span&gt;. Selecting this solved my problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-4115562864888073501?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/4115562864888073501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/07/report-viewer-fun-and-games.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/4115562864888073501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/4115562864888073501'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/07/report-viewer-fun-and-games.html' title='Report Viewer Fun And Games'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_i8oXuszBfQ0/SnGP2mRzh1I/AAAAAAAAAAw/vhmFH8bcpv8/s72-c/AllowNull.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-6154058175430091856</id><published>2009-05-19T08:50:00.002+01:00</published><updated>2009-05-19T08:59:40.208+01:00</updated><title type='text'>ASP.NET Unit Testing and TypeMock</title><content type='html'>I've been using TypeMock since 2005 and I find it a useful tool to have in my toolbox.  I don't subscribe to the "it's too powerful and too easy to do things wrong" school of thought.  My take on it is that it's really powerful and is especially useful when bringing legacy code under control.  Anyway, TypeMock are releasing an ASP.NET bundle. See the details below.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.typemock.com/"&gt;Unit Testing&lt;/a&gt; ASP.NET? &lt;a href="http://www.typemock.com/ASP.NET_unit_testing_page.php"&gt;ASP.NET unit testing&lt;/a&gt; has never been this easy.&lt;br /&gt;&lt;br /&gt;Typemock is launching a new product for ASP.NET developers &amp;#8211; the &lt;strong&gt;ASP.NET Bundle&lt;/strong&gt; - and for the launch will be giving out &lt;span style="color:#006600;"&gt;&lt;strong&gt;FREE licenses&lt;/strong&gt;&lt;/span&gt; to bloggers and their readers.&lt;br /&gt;&lt;br /&gt;The ASP.NET Bundle is the ultimate ASP.NET unit testing solution, and offers both &lt;a href="http://www.typemock.com/"&gt;Typemock Isolator&lt;/a&gt;, a &lt;a href="http://www.typemock.com/"&gt;unit test&lt;/a&gt; tool and &lt;a href="http://sm-art.biz/Ivonna.aspx"&gt;Ivonna&lt;/a&gt;, the Isolator add-on for &lt;a href="http://sm-art.biz/Ivonna.aspx"&gt;ASP.NET unit testing&lt;/a&gt;, for a bargain price.&lt;br /&gt;&lt;br /&gt;Typemock Isolator is a leading &lt;a href="http://www.typemock.com/"&gt;.NET unit testing&lt;/a&gt; tool (C# and VB.NET) for many &amp;#8216;hard to test&amp;#8217; technologies such as &lt;a href="http://typemock.com/sharepointpage.php"&gt;SharePoint&lt;/a&gt;, &lt;a href="http://www.typemock.com/ASP.NET_unit_testing_page.php"&gt;ASP.NET&lt;/a&gt;, &lt;a href="http://www.typemock.com/ASP.NET_unit_testing_page.php"&gt;MVC&lt;/a&gt;, &lt;a href="http://www.typemock.com/wcfpage.php"&gt;WCF&lt;/a&gt;, WPF, &lt;a href="http://www.typemock.com/Silverlight_unit_testing_page.php"&gt;Silverlight&lt;/a&gt; and more. Note that for &lt;a href="http://www.typemock.com/Silverlight_unit_testing_page.php"&gt;unit testing Silverlight&lt;/a&gt; there is an open source Isolator add-on called &lt;a href="http://www.typemock.com/Silverlight_unit_testing_page.php"&gt;SilverUnit&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first 60 bloggers who will blog this text in their blog and &lt;a href="http://blog.typemock.com/2009/05/get-free-typemock-licenses-aspnet.html"&gt;tell us about it&lt;/a&gt;, will get a Free Isolator ASP.NET Bundle license (Typemock Isolator + Ivonna). If you post this in an ASP.NET &lt;strong&gt;dedicated&lt;/strong&gt; blog, you'll get a license automatically (even if more than 60 submit) during the first week of this announcement.&lt;br /&gt;&lt;br /&gt;Also 8 bloggers will get an &lt;strong&gt;additional 2 licenses&lt;/strong&gt; (each) to give away to their readers / friends.&lt;br /&gt;&lt;br /&gt;Go ahead, click the following link for &lt;a href="http://blog.typemock.com/2009/05/get-free-typemock-licenses-aspnet.html"&gt;more information &lt;/a&gt;on how to get your free license.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-6154058175430091856?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/6154058175430091856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/05/aspnet-unit-testing-and-typemock.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/6154058175430091856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/6154058175430091856'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/05/aspnet-unit-testing-and-typemock.html' title='ASP.NET Unit Testing and TypeMock'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-6908504419548759800</id><published>2009-05-13T13:54:00.002+01:00</published><updated>2009-05-13T14:04:05.418+01:00</updated><title type='text'>Towards a New Architect</title><content type='html'>I'm attending a couple of sessions by &lt;a href="http://codebetter.com/blogs/david_laribee/"&gt;David Laribee&lt;/a&gt; on software development process.   The sessions are based on Agile\Lean development ideas.  He's well worth seeing if you're interested in that sort of thing and his sessions today have been very interactive.  Anyway, the reason for this post is to put some links up for James because he was too lazy to write them down at the time ;-).&lt;br /&gt;  &lt;DL&gt;&lt;p&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.pragprog.com/titles/ahptl/pragmatic-thinking-and-learning"&gt;The Pragmatic Bookshelf | Pragmatic Thinking and Learning&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.useit.com/papers/heuristic/heuristic_list.html"&gt;Heuristics for User Interface Design&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.google.co.uk/search?hl=en&amp;q=agile+pommodoro+technique+free+e-book&amp;btnG=Search&amp;meta="&gt;agile pommodoro technique free e-book - Google Search&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://iqueryable.com/2007/08/09/AgileAdviceFromFredGeorge.aspx"&gt;Steve Eichert - Agile Advice from Fred George&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.pomodorotechnique.com/resources/cirillo/ThePomodoroTechnique_v1-3.pdf"&gt;http://www.pomodorotechnique.com/resources/cirillo/ThePomodoroTechnique_v1-3.pdf&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.amazon.co.uk/s/ref=nb_ss_w_h__0_14?url=search-alias%3Daps&amp;field-keywords=refactor+your+wetware&amp;x=0&amp;y=0&amp;sprefix=refactor+your+"&gt;Amazon.co.uk: refactor your wetware&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.omnigroup.com/applications/OmniGraffle/"&gt;The Omni Group - OmniGraffle&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.google.co.uk/search?source=ig&amp;hl=en&amp;rlz=&amp;q=david+anderson+agile+management&amp;btnG=Google+Search&amp;meta=lr%3D"&gt;david anderson agile management - Google Search&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.google.co.uk/search?source=ig&amp;hl=en&amp;rlz=&amp;q=feature+crews+microsoft&amp;btnG=Google+Search&amp;meta=lr%3D"&gt;feature crews microsoft - Google Search&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.google.co.uk/search?source=ig&amp;hl=en&amp;rlz=&amp;q=osgi&amp;btnG=Google+Search&amp;meta=lr%3D"&gt;osgi - Google Search&lt;/A&gt;&lt;br /&gt;   &lt;DT&gt;&lt;A HREF="http://www.google.co.uk/search?source=ig&amp;hl=en&amp;rlz=&amp;q=liquibase&amp;btnG=Google+Search&amp;meta=lr%3D"&gt;liquibase - Google Search&lt;/A&gt;&lt;br /&gt;  &lt;/DL&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-6908504419548759800?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/6908504419548759800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/05/towards-new-architect.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/6908504419548759800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/6908504419548759800'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/05/towards-new-architect.html' title='Towards a New Architect'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-3878407981848291774</id><published>2009-04-27T20:40:00.003+01:00</published><updated>2009-04-27T20:48:51.081+01:00</updated><title type='text'>Progressive.Net Tutorials 2009</title><content type='html'>I'm looking forward to attending this event in May.  It looks like there will be some interesting sessions and it'll be good to catch up with London friends.&lt;/br&gt;&lt;br /&gt;&lt;a href="http://skillsmatter.com/event/open-source-dot-net/progressive-dot-net-exchange"&gt;&lt;img src="http://skillsmatter.com/custom/banners/opensource-dot-net-tutorials-coming100x100.gif" ALT="WebTech eXchange 2009" TITLE="WebTech eXchange 2009"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-3878407981848291774?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/3878407981848291774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/04/progressivenet-tutorials-2009.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3878407981848291774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3878407981848291774'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/04/progressivenet-tutorials-2009.html' title='Progressive.Net Tutorials 2009'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-3085632439514033958</id><published>2009-03-12T17:37:00.002Z</published><updated>2009-03-12T17:40:25.806Z</updated><title type='text'>error ASPPARSE: Could not load type 'Global'</title><content type='html'>I'm working on an ASP.Net 2.0 project using VS 2005 and so I thought I'd take the opportunity to try out the &lt;a href="http://msdn.microsoft.com/en-us/asp.net/aa336619.aspx" title="Visual Studio 2005 Web Deployment Projects" target="_blank"&gt;Visual Studio 2005 Web Deployment Projects&lt;/a&gt; (WDP).  &lt;br /&gt;&lt;br /&gt;All went well up until the point I tried to build the deployment project.  The build failed with the "error ASPPARSE: Could not load type 'Global' " error. I looked for a solution on the Web and It turns out that Asp_net compiler wants a "bin" folder with all the dll references inside the project (the one you are tyring to build).  After some more research I found the answer to my problem.  &lt;br /&gt;&lt;br /&gt;There is an element in the wdproj file (the MSBuild file created by the WDP) called 'SourceWebPhysicalPath'.  This contained the value '..\PDR' (where PDR is the name of my Web application).  Using a text editor to change this value to '..\PDR\bin' fixed the problem.  The complete element is &lt;code&gt;&amp;lt;SourceWebPhysicalPath&amp;gt;..\PDR\bin&amp;lt;/SourceWebPhysicalPath&amp;gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-3085632439514033958?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/3085632439514033958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/03/error-aspparse-could-not-load-type.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3085632439514033958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3085632439514033958'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/03/error-aspparse-could-not-load-type.html' title='error ASPPARSE: Could not load type &apos;Global&apos;'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-3351146424161917237</id><published>2009-02-05T16:48:00.001Z</published><updated>2009-02-05T16:48:43.656Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>Watchout, there's a Host about</title><content type='html'>&lt;p style="clear: both"&gt;I was pairing with Remco (start a blog man!) today and we came across an interesting assumption. The code we were looking at created a redirect URL using the following code.&lt;/p&gt;&lt;p style="clear: both"&gt;&lt;br /&gt; return Redirect("http://" + Request.Url.Host + "/" + url.Trim('/'));&lt;/p&gt;&lt;p style="clear: both"&gt;'Host' returns the "host component of this instance". No bad thing, until you start to test on a server using a port other than port 80. Your code may well break because the URL you are constructing doesn't contain the port number that your Web application is running on. To fix this you can use Request.Url.Authority. 'Authority' return the "DNS host name or IP address and the port number for a server". &lt;/p&gt;&lt;br class='final-break' style='clear: both' /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-3351146424161917237?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/3351146424161917237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/02/watchout-there-host-about.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3351146424161917237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3351146424161917237'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/02/watchout-there-host-about.html' title='Watchout, there&amp;#39;s a Host about'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-564069000740928242</id><published>2009-02-03T00:02:00.001Z</published><updated>2009-02-03T00:02:53.438Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><title type='text'>ActiveRecord Configuration</title><content type='html'>&lt;p&gt;The quick-start documentation that comes with &lt;a href="http://www.castleproject.org/activerecord/" title="Link to ActiveRecord web site."&gt;ActiveRecord&lt;/a&gt; provides the following example configuration.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;activerecord&amp;gt;&lt;br /&gt;&amp;lt;config&amp;gt;&lt;br /&gt;&amp;lt;add key="connection.driver_class" value="NHibernate.Driver.SqlClientDriver" /&amp;gt;&lt;br /&gt;&amp;lt;add key="dialect" value="NHibernate.Dialect.MsSql2005Dialect" /&amp;gt;&lt;br /&gt;&amp;lt;add key="connection.provider" value="NHibernate.Connection.DriverConnectionProvider" /&amp;gt;&lt;br /&gt;&amp;lt;add key="connection.connection_string" value="Data Source=.;Initial Catalog=test;Integrated Security=SSPI" /&amp;gt;&lt;br /&gt;&amp;lt;/config&amp;gt;&lt;br /&gt;&amp;lt;/activerecord&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;I couldn't get this to work. After a bit of fiddling I ended up with the following.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;activerecord&amp;gt;&lt;br /&gt;&amp;lt;config&amp;gt;&lt;br /&gt;&amp;lt;add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" /&amp;gt;&lt;br /&gt;&amp;lt;add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect" /&amp;gt;&lt;br /&gt;&amp;lt;add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" /&amp;gt;&lt;br /&gt;&amp;lt;add key="hibernate.connection.connection_string" value="Server=.;Initial Catalog=TestDatabase;User Id=UserNameGoesHere;Password=PasswordGoesHere " /&amp;gt;&lt;br /&gt;&amp;lt;/config&amp;gt;&lt;br /&gt;&amp;lt;/activerecord&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The main differences are the 'hibernate' prefixes in the keys and the replacement of Data Source with Server in the connection string. This configuration worked against a SQL Server 2005 installation.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-564069000740928242?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/564069000740928242/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/02/activerecord-configuration.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/564069000740928242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/564069000740928242'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/02/activerecord-configuration.html' title='ActiveRecord Configuration'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-3768974305522374584</id><published>2009-02-02T15:32:00.001Z</published><updated>2009-02-02T15:37:32.129Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Hardware'/><category scheme='http://www.blogger.com/atom/ns#' term='TCP/IP'/><category scheme='http://www.blogger.com/atom/ns#' term='Networks'/><title type='text'>The Microsoft Loopback Adapter</title><content type='html'>&lt;p&gt;I had a situation once where the IP address of an SMTP server had been hard-coded and I could only run the application successfully if the server was available. This meant that developing off-site was a problem. Then, from somewhere in the back of my mind, I remembered about the Microsoft Loopback Adapter (MSLA). This is a software network adapter i.e. you don't have to physically install a NIC. Installing this network adapter (add new hardware and choose the Microsoft Loopback Adapter from the list) allows me to easily route a given IP address to my local machine. For instance, if I manually assign the IP address of the MSLA to 192.168.0.100, then any requests bound for this IP address from my machine will end up at my machine. It's like saying "route any requests to 192.168.0.100 to 127.0.0.1". I installed a local SMTP server and my application sent emails to this local server via the MSLA. All I had to do was to remember to disable the network adapter when I was back on-site and wanted to use the real SMTP server.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-3768974305522374584?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/3768974305522374584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/02/microsoft-loopback-adapter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3768974305522374584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3768974305522374584'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/02/microsoft-loopback-adapter.html' title='The Microsoft Loopback Adapter'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-3731536970095247937</id><published>2009-01-23T19:31:00.001Z</published><updated>2009-01-23T19:32:44.808Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='A Bit Of Fun'/><title type='text'>Typealyser</title><content type='html'>&lt;p&gt;Apparently, I'm a mechanic.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.typealyzer.com" title="A link to typealyser"&gt;http://www.typealyzer.com&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-3731536970095247937?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/3731536970095247937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/01/typealyser.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3731536970095247937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3731536970095247937'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/01/typealyser.html' title='Typealyser'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-3462721896949175508</id><published>2009-01-21T08:00:00.000Z</published><updated>2009-01-23T22:05:04.712Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='A Bit Of Fun'/><title type='text'>Cooking Up An Application</title><content type='html'>&lt;p&gt;One of the things I like to do at the weekend is cook a nice meal. I enjoy the whole process of selecting and preparing the ingredients and then putting them together to produce something that (usually) tastes good and leaves me wanting more. It occurred to me, whilst I was walking the dog this morning &lt;a href="#LinkOne"&gt;1&lt;/a&gt;, that software development is quite a lot like cooking in many ways. I did a quick search on the Web and chuckled to myself as I read the advice given to people who wanted to cook. You could almost take the advice, word for word, and apply it to software development. Let me share some examples.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The cook's version&lt;/strong&gt;&lt;br /&gt;"Nobody likes a dirty kitchen, and a dirty kitchen is no fun to cook in either (not to mention unsanitary). With a little conscious effort, you can keep your kitchen clean while you cook. "&lt;br /&gt;&lt;strong&gt;The developer's version&lt;/strong&gt;&lt;br /&gt;Nobody likes dirty code, and dirty code is no fun to develop either (not to mention unsanitary). With a little conscious effort, you can keep your code clean while you develop.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The cook's version&lt;/strong&gt;&lt;br /&gt;Be organized before you start cooking. It is important to have all of your ingredients and equipment assembled before you start cooking. This will help you follow the recipe more easily and prevent any messing around looking for ingredients and equipment that you didn't realise you needed—or maybe don't even have!&lt;br /&gt;&lt;strong&gt;The developer's version&lt;/strong&gt;&lt;br /&gt;Be organized before you start developing. It is important to have all of your requirements and tools assembled before you start developing. This will help you follow the recipe more easily and prevent any messing around looking for requirements and tools that you didn't realise you needed—or maybe don't even have!&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The cook's version&lt;/strong&gt;&lt;br /&gt;Stick to the recipe. When you are a beginner cook, you should follow the recipe exactly. As you cook more, you will become more at ease with making changes to a recipe and still create successful dishes.&lt;br /&gt;&lt;strong&gt;The developer's version&lt;/strong&gt;&lt;br /&gt;Stick to the patterns. When you are a beginner developer, you should follow the patterns exactly. As you develop more, you will become more at ease with making changes to a pattern and still create successful applications.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The cook's version&lt;/strong&gt;&lt;br /&gt;Clean up. It is easier if you can clean as you go but don't worry if this doesn't come naturally at first. After a while, you'll work out that this is easier than cooking in a mess! Just make sure that you clean up after yourself when you have finished cooking, and don't forget any spills on the floor or cupboard doors.&lt;br /&gt;&lt;strong&gt;The developer's version&lt;/strong&gt;&lt;br /&gt;Clean up. It is easier if you can clean as you go but don't worry if this doesn't come naturally at first. After a while, you'll work out that this is easier than developing in a mess! Just make sure that you clean up after yourself when you have finished coding, and don't forget any spills in the test code.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The cooks version&lt;/strong&gt;&lt;br /&gt;Enjoy your experience. Cooking is fun and a creative activity. When you feel a little more confident, start experimenting with different ingredients and come up with your own creations.&lt;br /&gt;&lt;strong&gt;The developer's version&lt;/strong&gt;&lt;br /&gt;Enjoy your experience. Developing is fun and a creative activity. When you feel a little more confident, start experimenting with different applications and come up with your own creations.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;a name="LinkOne" id="LinkOne"&gt;1&lt;/a&gt; : If you find yourself needing thinking time buy yourself a dog. Larger ones need lots of walking and this is an ideal time to let your brain sort stuff out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-3462721896949175508?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/3462721896949175508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/01/cooking-up-application.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3462721896949175508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/3462721896949175508'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/01/cooking-up-application.html' title='Cooking Up An Application'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-6209188083691287074</id><published>2009-01-19T07:54:00.000Z</published><updated>2009-01-19T07:55:08.928Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='NUnit'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Duplication, NUnit, Row Tests and MVC Views</title><content type='html'>&lt;p&gt;I'm working on a project that uses the ASP.NET MVC framework. Learning how to use this is fun and I like the fact that I am able to write code that feels cleaner to me. We are working with preview 4 at the moment but should be moving to the release candidate as soon as it becomes available. I'm really looking forward to some of the "post preview 4" features, such as Model Binder support and the AcceptVerbs attribute. One of the nice things about developing with this framework is that it makes unit testing Web sites a whole lot easier. This is because the "controller" part of MVC is just a standard class that you can write unit tests against.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I came up with a neat piece of code as I was writing a test that checked the value of a variable stored in ViewData. I'm not saying it's new or original, just that it evolved naturally from my use of Test Driven Development (TDD). The value being checked was an enumeration, which was used to control an aspect of the Web page style. The value was different for each action on the controller and we had eleven actions. I wanted to test that the expected value was present in the view returned from each action. I have an example of the sort of thing that I was trying to do that you can download from &lt;a href="http://code.google.com/p/gbarrs/source/browse/#svn/trunk/Stuff" title="my Google Code project"&gt;my Google Code project&lt;/a&gt;. Here is the unit test I wrote for the example (I use 'MethodUnderTest_Scenario_ExpectedBehaviour' as my test naming convention).&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&lt;span style="color: #2b91af"&gt;Test&lt;/span&gt;]&lt;br /&gt;        [&lt;span style="color: #2b91af"&gt;Category&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Unit"&lt;/span&gt;)]&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index_IndexActionCalled_ViewDataContainsExpectedColour()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000"&gt;// arrange&lt;/span&gt;&lt;br /&gt;            var theExpectedColour = &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;.red;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// act&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; homeController = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;HomeController&lt;/span&gt;();&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; viewResult = homeController.Index()&lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ViewResult&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// assert&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(viewResult, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.Not.Null);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (viewResult == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; || !(viewResult.ViewData[&lt;span style="color: #a31515"&gt;"Colour"&lt;/span&gt;] &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #000000"&gt;                &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Fail(&lt;/span&gt;"ViewData does not contain a Colour."&lt;span style="color: #000000"&gt;);&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; actualColour = (&lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;)viewResult.ViewData[&lt;span style="color: #a31515"&gt;"Colour"&lt;/span&gt;];&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(actualColour, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.EqualTo(theExpectedColour));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Once I made this test pass I moved on to the next one.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&lt;span style="color: #2b91af"&gt;Test&lt;/span&gt;]&lt;br /&gt;        [&lt;span style="color: #2b91af"&gt;Category&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Unit"&lt;/span&gt;)]&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; About_AboutActionCalled_ViewDataContainsExpectedColour()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000"&gt;// arrange&lt;/span&gt;&lt;br /&gt;            &lt;span style="border: solid #0000FF"&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt;&lt;span style="color: #0000ff"&gt; theExpectedColour = &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;.blue;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// act&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; homeController = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;HomeController&lt;/span&gt;();&lt;br /&gt;            &lt;span style="border: solid #0000FF"&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; viewResult = homeController.About() &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ViewResult&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// assert&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(viewResult, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.Not.Null);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (viewResult == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; || !(viewResult.ViewData[&lt;span style="color: #a31515"&gt;"Colour"&lt;/span&gt;] &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #000000"&gt;                &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Fail(&lt;/span&gt;"ViewData does not contain a Colour."&lt;span style="color: #000000"&gt;);&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; actualColour = (&lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;)viewResult.ViewData[&lt;span style="color: #a31515"&gt;"Colour"&lt;/span&gt;];&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(actualColour, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.EqualTo(theExpectedColour));&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;I got this second test passing and noticed that there was a lot of duplication in my test code. It is good TDD practice to treat test code the same as production code, so my next step was to refactor the test code. The sections outlined in blue above show the code differences and those differences are 1) the expected colour and 2) the name of the method being called. To refactor this I would need to have a test that takes parameters. I could then pass in the expected colour and the name of the method to be called. Reflection could then be used to call the method. This is where NUnit RowTest attributes come into play. RowTest attributes are part of nunit.framework.extensions.dll. Adding a reference to this dll allows me to create parameterised unit tests. The next stage of my refactoring was to implement a parameterised unit test.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&lt;span style="color: #2b91af"&gt;RowTest&lt;/span&gt;]&lt;br /&gt;        [&lt;span style="color: #2b91af"&gt;Row&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"About"&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;.blue)]&lt;br /&gt;        [&lt;span style="color: #2b91af"&gt;Category&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Unit"&lt;/span&gt;)]&lt;br /&gt;&lt;span style="color: #0000ff"&gt;        public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; About_AboutActionCalled_ViewDataContainsExpectedColour(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; methodName, &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt; expectedColour)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000"&gt;// arrange&lt;br /&gt; &lt;span style="color: #000000;"&gt;           &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; theExpectedColour = expectedColour;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// act&lt;br /&gt; &lt;span style="color: #000000;"&gt;           &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; homeController = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;HomeController&lt;/span&gt;();&lt;br /&gt;            &lt;span style="color:#008000"&gt;// Use reflection to call the action method&lt;br /&gt;&lt;/span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; controllerType = homeController.GetType();&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; methodToTest = controllerType.GetMethod(methodName);&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(methodToTest, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.Not.Null, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;"No method called {0} found."&lt;/span&gt;, methodName));&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; viewResult = methodToTest.Invoke(homeController, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ViewResult&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// assert&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(viewResult, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.Not.Null);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (viewResult == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; || !(viewResult.ViewData[&lt;span style="color: #a31515"&gt;"Colour"&lt;/span&gt;] &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #000000"&gt;                &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Fail(&lt;/span&gt;"ViewData does not contain a Colour."&lt;span style="color: #000000"&gt;);&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; actualColour = (&lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;)viewResult.ViewData[&lt;span style="color: #a31515"&gt;"Colour"&lt;/span&gt;];&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(actualColour, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.EqualTo(theExpectedColour));&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;The method signature was changed to take the name of the method to be called and the expected colour. The call to homeController.About() is now carried out using reflection. This test passed and so I added a new Row attribute to test the call to homeController.Index().&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&lt;span style="color: #2B91AF;"&gt;RowTest&lt;/span&gt;]&lt;br /&gt;        [&lt;span style="color: #2B91AF;"&gt;Row&lt;/span&gt;(&lt;span style="color: #A31515;"&gt;"About"&lt;/span&gt;, &lt;span style="color: #2B91AF;"&gt;Colour&lt;/span&gt;.blue)]&lt;br /&gt;        [&lt;span style="color: #2B91AF;"&gt;Row&lt;/span&gt;(&lt;span style="color: #A31515;"&gt;"Index"&lt;/span&gt;, &lt;span style="color: #2B91AF;"&gt;Colour&lt;/span&gt;.red)] &lt;br /&gt;        [&lt;span style="color: #2B91AF;"&gt;Category&lt;/span&gt;(&lt;span style="color: #A31515;"&gt;"Unit"&lt;/span&gt;)]&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;        public&lt;/span&gt; &lt;span style="color: #0000FF;"&gt;void&lt;/span&gt; About_AboutActionCalled_ViewDataContainsExpectedColour(&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt; methodName, &lt;span style="color: #2B91AF;"&gt;Colour&lt;/span&gt; expectedColour)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;// arrange&lt;br /&gt; &lt;span style="color: #000000;"&gt;           &lt;span style="color: #0000FF;"&gt;var&lt;/span&gt; theExpectedColour = expectedColour;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;// act&lt;br /&gt; &lt;span style="color: #000000;"&gt;           &lt;span style="color: #0000FF;"&gt;var&lt;/span&gt; homeController = &lt;span style="color: #0000FF;"&gt;new&lt;/span&gt; &lt;span style="color: #2B91AF;"&gt;HomeController&lt;/span&gt;();&lt;br /&gt;            &lt;span style="color: #008000;"&gt;// Use reflection to call the action method&lt;br /&gt;&lt;/span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt; controllerType = homeController.GetType();&lt;br /&gt;            &lt;span style="color: #0000FF;"&gt;var&lt;/span&gt; methodToTest = controllerType.GetMethod(methodName);&lt;br /&gt;            &lt;span style="color: #2B91AF;"&gt;Assert&lt;/span&gt;.That(methodToTest, &lt;span style="color: #2B91AF;"&gt;Is&lt;/span&gt;.Not.Null, &lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #A31515;"&gt;"No method called {0} found."&lt;/span&gt;, methodName));&lt;br /&gt;            &lt;span style="color: #0000FF;"&gt;var&lt;/span&gt; viewResult = methodToTest.Invoke(homeController, &lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;) &lt;span style="color: #0000FF;"&gt;as&lt;/span&gt; &lt;span style="color: #2B91AF;"&gt;ViewResult&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;// assert&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #2B91AF;"&gt;Assert&lt;/span&gt;.That(viewResult, &lt;span style="color: #2B91AF;"&gt;Is&lt;/span&gt;.Not.Null);&lt;br /&gt;            &lt;span style="color: #0000FF;"&gt;if&lt;/span&gt; (viewResult == &lt;span style="color: #0000FF;"&gt;null&lt;/span&gt; || !(viewResult.ViewData[&lt;span style="color: #A31515;"&gt;"Colour"&lt;/span&gt;] &lt;span style="color: #0000FF;"&gt;is&lt;/span&gt; &lt;span style="color: #2B91AF;"&gt;Colour&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #000000;"&gt;                &lt;/span&gt;&lt;span style="color: #2B91AF;"&gt;Assert&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Fail(&lt;/span&gt;"ViewData does not contain a Colour."&lt;span style="color: #000000;"&gt;);&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000FF;"&gt;var&lt;/span&gt; actualColour = (&lt;span style="color: #2B91AF;"&gt;Colour&lt;/span&gt;)viewResult.ViewData[&lt;span style="color: #A31515;"&gt;"Colour"&lt;/span&gt;];&lt;br /&gt;            &lt;span style="color: #2B91AF;"&gt;Assert&lt;/span&gt;.That(actualColour, &lt;span style="color: #2B91AF;"&gt;Is&lt;/span&gt;.EqualTo(theExpectedColour));&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;Adding new tests for this scenario simply becomes a case of adding more Row attributes. I made a couple of final changes before I was happy with this test. I felt the reflection code distracted from the intent of the test, so I used the "Extract Method" refactoring to pull that code out into a separate method. I also renamed the methodName parameter to actionName. Using methodName wasn't wrong, I just feel that actionName describes the intent of what is being tested better. We are calling action methods on a controller. It's just a little more explicit than saying we are calling methods on a controller. Also, my naming convention is not quite right for this test because About is no longer the method under test. I decide to use HomeController_ActionCalled_ViewDataContainsExpectedColour as a method name to describe the intent of the test.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&lt;span style="color: #2b91af"&gt;RowTest&lt;/span&gt;]&lt;br /&gt;        [&lt;span style="color: #2b91af"&gt;Row&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Index"&lt;/span&gt;,&lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;.red)]&lt;br /&gt;        [&lt;span style="color: #2b91af"&gt;Row&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"About"&lt;/span&gt;,&lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;.blue)]&lt;br /&gt;        [&lt;span style="color: #2b91af"&gt;Category&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Unit"&lt;/span&gt;)]&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; HomeController_ActionCalled_ViewDataContainsExpectedColour(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; actionName, &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt; expectedColour)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000"&gt;// arrange&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; theExpectedColour = expectedColour;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// act&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; homeController = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;HomeController&lt;/span&gt;();&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; viewResult = CallControllerMethodAndReturnViewResult(homeController, actionName) ;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// assert&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(viewResult, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.Not.Null);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (viewResult == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; || !(viewResult.ViewData[&lt;span style="color: #a31515"&gt;"Colour"&lt;/span&gt;] &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #000000"&gt;                &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Fail(&lt;/span&gt;"ViewData does not contain a Colour."&lt;span style="color: #000000"&gt;);&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; actualColour = (&lt;span style="color: #2b91af"&gt;Colour&lt;/span&gt;)viewResult.ViewData[&lt;span style="color: #a31515"&gt;"Colour"&lt;/span&gt;];&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(actualColour, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.EqualTo(theExpectedColour));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ViewResult&lt;/span&gt; CallControllerMethodAndReturnViewResult(&lt;span style="color: #2b91af"&gt;Controller&lt;/span&gt; controller, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; methodName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; controllerType = controller.GetType();&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; methodToTest = controllerType.GetMethod(methodName);&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Assert&lt;/span&gt;.That(methodToTest, &lt;span style="color: #2b91af"&gt;Is&lt;/span&gt;.Not.Null, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;"No method called {0} found."&lt;/span&gt;, methodName));&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; methodToTest.Invoke(controller, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ViewResult&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;I like the result of this refactoring. The code is neat, compact and easily understandable. Any developer looking at this code should quickly be able to understand the expected behaviour of the code under test.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-6209188083691287074?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/6209188083691287074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/01/duplication-nunit-row-tests-and-mvc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/6209188083691287074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/6209188083691287074'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/01/duplication-nunit-row-tests-and-mvc.html' title='Duplication, NUnit, Row Tests and MVC Views'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-5639979432762510645</id><published>2009-01-16T07:41:00.001Z</published><updated>2009-01-16T07:41:09.087Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Code'/><category scheme='http://www.blogger.com/atom/ns#' term='SVN'/><category scheme='http://www.blogger.com/atom/ns#' term='SVNX'/><title type='text'>SVNX Security Certificate Problem</title><content type='html'>&lt;p&gt;I'm looking at how I can usefully use Google products. Someone at the company I am working at uses Google Code to host code examples, which seems like a good idea to me. I set myself up with a Google Code account, fired up &lt;a href="http://www.lachoseinteractive.net/en/community/subversion/svnx/features/" title="Link To SVNX product page."&gt;SVNX&lt;/a&gt; and tried to connect to my new SVN repository. The connection failed because the certificate issued by Google was not trusted by SVN. A quick Google search came up with &lt;a href="http://www.dikant.de/2007/08/27/importing-ssl-certificates-into-svnx/" title="Link to blog post"&gt;Importing SSL certificates into svnX&lt;/a&gt; . This post explains how to use the command line to import a certificate and after following the instructions I was able to connect successfully to the repository.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-5639979432762510645?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/5639979432762510645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/01/svnx-security-certificate-problem.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/5639979432762510645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/5639979432762510645'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/01/svnx-security-certificate-problem.html' title='SVNX Security Certificate Problem'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8588149298977634954.post-182867708660819591</id><published>2009-01-15T21:09:00.000Z</published><updated>2009-01-15T21:11:12.511Z</updated><title type='text'>Hello</title><content type='html'>&lt;p&gt;...world&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8588149298977634954-182867708660819591?l=gbarrs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gbarrs.blogspot.com/feeds/182867708660819591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gbarrs.blogspot.com/2009/01/hello.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/182867708660819591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8588149298977634954/posts/default/182867708660819591'/><link rel='alternate' type='text/html' href='http://gbarrs.blogspot.com/2009/01/hello.html' title='Hello'/><author><name>Gordon Barrs</name><uri>http://www.blogger.com/profile/15683732370777543275</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_i8oXuszBfQ0/SW-MvGQndMI/AAAAAAAAAAM/_82C_KjChRk/S220/IMGP0112.JPG'/></author><thr:total>0</thr:total></entry></feed>
