<?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-9168000460138974508</id><updated>2012-02-16T17:14:53.577Z</updated><category term='MongoDB'/><category term='Ju.Ju.'/><category term='Behaviour Driven Development'/><category term='node.js'/><category term='Cartoon'/><category term='Git'/><category term='Appharbor'/><category term='MSpec'/><category term='specification.patterns'/><category term='Test Driven Development'/><category term='Ruby'/><category term='Cucumber'/><category term='Javascript'/><category term='family'/><category term='SpecFlow'/><category term='Socket.IO'/><category term='ASP.Net MVC'/><category term='NoSQL'/><category term='CouchDB'/><category term='Continuous Testing'/><title type='text'>airasoul</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-4846117338123464150</id><published>2012-01-26T22:00:00.005Z</published><updated>2012-01-26T22:16:31.121Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='family'/><title type='text'>Soothe a soul</title><content type='html'>&lt;iframe width="420" height="315" src="http://www.youtube.com/embed/fTDymyJyvgo" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-4846117338123464150?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/4846117338123464150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2012/01/soothe-soul.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/4846117338123464150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/4846117338123464150'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2012/01/soothe-soul.html' title='Soothe a soul'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/fTDymyJyvgo/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-6964363290548110322</id><published>2012-01-07T00:04:00.004Z</published><updated>2012-01-07T09:09:12.577Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.Net MVC'/><title type='text'>Solidifying ASP.Net MVC with a single action per controller</title><content type='html'>&lt;b&gt;rza - a razor sharp folder structure for ASP.Net MVC&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I recently watched Uncle Bobs skillsmatter cast on &lt;a href="http://skillsmatter.com/podcast/agile-testing/uncle-bob-web-architecture"&gt;web architecture&lt;/a&gt;; interesting stuff.  &lt;br /&gt;&lt;br /&gt;This got me thinking about web architectures and how ASP.Net MVC applications of course suffer from the same issues Bob outlined with his rails application.  &lt;br /&gt;&lt;br /&gt;When looking at a web application code base all you see is web stuff; controllers/models/views nothing to do with the domain; you could not when looking at the root level of the codebase identify what the application did.&lt;br /&gt;&lt;br /&gt;Well; I have recently been playing around with the idea of using a single action per controller in order to&lt;br /&gt;&lt;br /&gt;- solidfy my controllers; MVCs noted SRP/OCP issues&lt;br /&gt;- reduce the number of contributors injected into a class&lt;br /&gt;- clean up specifications; in order to avoid stubbing out unused contributors&lt;br /&gt;&lt;br /&gt;I have also been toying with the idea of changing my MVC folder structure in order to:&lt;br /&gt;&lt;br /&gt;- group contributors/classes for a feature into a single folder structure&lt;br /&gt;- include within that folder structure the specifications&lt;br /&gt;&lt;br /&gt;So this is the folder structure I have come up with which solves the above; as you can see the specifications are included in their relevant place within the code base. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-nSTWRD3b8FY/Twd-kqsFUBI/AAAAAAAAAHI/9FuuK7vOAss/s1600/rza.png" imageanchor="1" style=""&gt;&lt;img border="0" height="354" width="281" src="http://1.bp.blogspot.com/-nSTWRD3b8FY/Twd-kqsFUBI/AAAAAAAAAHI/9FuuK7vOAss/s400/rza.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This is achieved very simply by extending the razor view engine in order to shift the folder structure around; check it out:  &lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1572848.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;So; yeah; we are able to get a pretty good idea as to what this application does simply by looking in the features folder.&lt;br /&gt;&lt;br /&gt;I have converted a blank ASP.Net MVC solution into this new folder structure; you can grab this on &lt;a href="https://github.com/AndrewKeig/rza"&gt;GitHub&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-6964363290548110322?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/6964363290548110322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2012/01/solidifying-aspnet-mvc-with-single.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/6964363290548110322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/6964363290548110322'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2012/01/solidifying-aspnet-mvc-with-single.html' title='Solidifying ASP.Net MVC with a single action per controller'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-nSTWRD3b8FY/Twd-kqsFUBI/AAAAAAAAAHI/9FuuK7vOAss/s72-c/rza.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-5916000794627140215</id><published>2011-12-07T07:47:00.003Z</published><updated>2011-12-08T05:00:34.041Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>Experimentations in concurrency &amp; asynchronicity with Node.js and chums - Part 2</title><content type='html'>Core to node.js is the concept of events/event emitters.  In order for a module to emit and respond to events; all it need do is simply inherit from the events module.  In order to do this we require the 'events' and 'util' modules and use the util.inherits function to inherit from the event module.&lt;br /&gt;&lt;br /&gt;The bhikkhu module below exposes one function 'meditate'; the function emits a '.breath' event every 3 seconds. It gets the type of breath from a 'takeBreath()' function; which returns either 'in' or 'out'.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Gist 1, module bhikkhu emitting breathe events&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1438046.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;In order for our bhikkhu to respond to the '.breath' event; we simply subscribe to the event using the '.on' function.&lt;br /&gt;&lt;br /&gt;A call to 'meditate()' will start the bhikkhu breathing. The text 'bhikkhu observes in/out breathe' is written to the console every 3 seconds until we stop our bhikkhu from meditating.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Gist 2, meditating bhikkhu&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1438051.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;So why is all this important; well events and events emitters help to facilitate non-blocking IO in Node.js.  Imagine for example the 'takeBreath()' function took an eternity; well; having this wrapped up in an event you can subscribe to allows the functionality to be placed on to the event queue as a callback; this stops the event loop from blocking.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-5916000794627140215?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/5916000794627140215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/12/experimentations-in-concurrency.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/5916000794627140215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/5916000794627140215'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/12/experimentations-in-concurrency.html' title='Experimentations in concurrency &amp; asynchronicity with Node.js and chums - Part 2'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-8620936970928742531</id><published>2011-08-04T14:10:00.038+01:00</published><updated>2011-12-07T09:05:10.375Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><category scheme='http://www.blogger.com/atom/ns#' term='Socket.IO'/><title type='text'>Experimentations in concurrency &amp; asynchronicity with Node.js and chums - Part 1</title><content type='html'>&lt;b&gt;An introduction&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Node.js is a server side technology that provides an event-driven, non-blocking framework for building highly scalable; real time; network-based applications.  The main goal of Node.js is to simplify the development of building such non trivial applications.  Node.js is based on Google Chrome‘s V8 engine; node.js applications are written in javascript.&lt;br /&gt;&lt;br /&gt;Node.js is not an attempt to put javascript on the server-side; javascript is effectively used as a high level DSL Ryan Dahl; the inventor of Node.js; reasons for choosing javascript are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;its event-driven; and event-driven applications are easy to scale (explained later)&lt;/li&gt;&lt;li&gt;every web developer on the planet has used it; I think!&lt;/li&gt;&lt;li&gt;javascript up until now has no concept of IO.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Node Concepts&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Event-driven&lt;/i&gt;&lt;br /&gt;Node.js applications are effectively (slight over-simplification) a series of anonymous or named functions which are executed not in any specific order but based on events happening either on the client or server.  An important concept in Node.js is the event loop; Node.js programs are executed sequentially; but callbacks/requests are placed in an event queue; the Node event loop executes the events in the queue sequentially.  When all events have been executed; Node will exit the event loop and then wait for more events to be added to the queue.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Event loop example&lt;/i&gt;&lt;br /&gt;The below example is a simple node program which demonstrates the event loop.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1131937.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The first statement is a timeout which takes as input an anonymous function; this is the first event added to the event queue; and will be executed after 2 seconds; this is also the last statement to be executed&lt;/li&gt;&lt;li&gt;The second statement is a call to nextTick; which takes as input an anonymous function; this will be executed on the next tick of the event loop.  When all events/requests have been executed for the current event loop; this function will be the first executed on the next execution of the event loop.&lt;/li&gt;&lt;li&gt;The third statement is a call to nextTick;  this function will be the second executed on the next execution of the event loop.&lt;/li&gt;&lt;li&gt;Finally a call to console.log; which simply prints to the console. This is not added to the event queue&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Threading&lt;/i&gt; &lt;br /&gt;Node.js makes use of a single thread; this is important; Node does not spawn new threads as per the normal concurrency model other languages and frameworks adopt in order to scale; Node side-steps the concurrency issue by exploiting javascript's ability to create, pass and asynchronously execute simple callback functions.  &lt;br /&gt;&lt;br /&gt;Node.js achieves scalability by ensuring all IO bound calls are executed in a non blocking way; i.e. by executing the IO operation asynchronously; passing a callback to the IO bound operation; the callback is executed on completion of the IO operation.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Blocking IO&lt;/i&gt;&lt;br /&gt;Consider the following Node.js application which reads a file.  When the readFileSync call is executed the application waits for a response; the thread on which that call was made will now sit and wait for a response.  This thread could be doing useful work; possibly responding to new requests; it cannot; this is commonly refered to as 'blocking IO'.  &lt;br /&gt;&lt;br /&gt;&lt;i&gt;Example of blocking IO&lt;/i&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1133652.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Non Blocking IO&lt;/i&gt;&lt;br /&gt;Consider the same application using evented Node.js.  When the readFile call is executed a callback method is passed with it; the thread will not wait for the file to be read; it will pick up the next event in the queue; when the call is complete the callback function is called; and the processing for the request continues; this is commonly refered to as 'non blocking IO'.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Example of non blocking IO&lt;/i&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1133651.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;So why Node.js&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Node.js makes an excellent fit for applications that have long running IO connections.  Consider applications like Comet and HTML5 WebSockets; these make use of a lot of open connections; so a thread per connection does not scale. This is where node jumps to our rescue; with its single threaded; event-based model. &lt;br /&gt;&lt;br /&gt;&lt;!--&lt;b&gt;The hello world app&lt;/b&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1123559.js"&gt; &lt;/script&gt;--&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-8620936970928742531?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/8620936970928742531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/08/experimentations-in-concurrency.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/8620936970928742531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/8620936970928742531'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/08/experimentations-in-concurrency.html' title='Experimentations in concurrency &amp; asynchronicity with Node.js and chums - Part 1'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-570655989026683127</id><published>2011-07-19T17:17:00.001+01:00</published><updated>2011-12-07T07:56:12.825Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>Node.js on windows; without Cygwin :)</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-qOcvHh2fikw/TiWtwzt1VWI/AAAAAAAAAGA/E8ImMlkv-VA/s1600/node_windows.png" imageanchor="1" style=""&gt;&lt;img border="0" height="337" width="400" src="http://4.bp.blogspot.com/-qOcvHh2fikw/TiWtwzt1VWI/AAAAAAAAAGA/E8ImMlkv-VA/s400/node_windows.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://nodejs.org/#download"&gt;http://nodejs.org/#download&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-570655989026683127?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/570655989026683127/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/07/nodejs-on-windows-without-cygwin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/570655989026683127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/570655989026683127'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/07/nodejs-on-windows-without-cygwin.html' title='Node.js on windows; without Cygwin :)'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-qOcvHh2fikw/TiWtwzt1VWI/AAAAAAAAAGA/E8ImMlkv-VA/s72-c/node_windows.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-8201648858143023257</id><published>2011-07-19T08:29:00.002+01:00</published><updated>2011-07-19T08:34:21.308+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cucumber'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Behaviour Driven Development'/><title type='text'>Cucumber on Windows</title><content type='html'>I have spent the last few months learning &lt;a href="http://cukes.info/" target="_blank"&gt;Cucumber&lt;/a&gt;, Capybara and Ruby in order to automate my acceptance tests.  I have previously used &lt;a href="http://specflow.org/" target="_blank"&gt;SpecFlow&lt;/a&gt; which is a great tool; but I wanted to see if the grass was any greener on the other side.&lt;br /&gt;&lt;br /&gt;Below are a few tips to get anyone interested in doing the same up and running; I have included my gem listing with version numbers to assist.  I conclude with a summary of things to consider when using Cucumber for .NET acceptance testing.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Install Ruby 1.8.7&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In order to run Cucumber on Windows install ruby using the RubyInstaller.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Visit: &lt;a href="http://rubyinstaller.org/downloads/" target="_blank"&gt;http://rubyinstaller.org/downloads/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Install &lt;a href="http://rubyforge.org/frs/download.php/74293/rubyinstaller-1.8.7-p334.exe"&gt;ruby&lt;/a&gt; 1.8.7; do not download and install version 1.9.2; cucumber does-knee like 1.9.2&lt;/li&gt;&lt;li&gt;When installing ruby select the option to “Add Ruby executables to your PATH”.&lt;/li&gt;&lt;li&gt;In order to verify a correct installation open a command prompt and type &lt;br /&gt;ruby –v&lt;br /&gt;you should see a response back stating the version number .&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Install DevKit&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Visit: &lt;a href="http://rubyinstaller.org/downloads/" target="_blank"&gt;http://rubyinstaller.org/downloads/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Download and then extract &lt;a href="http://github.com/downloads/oneclick/rubyinstaller/DevKit-tdm-32-4.5.1-20101214-1400-sfx.exe"&gt;DevKit&lt;/a&gt; to a folder somwhere on your drive (not important where)&lt;/li&gt;&lt;li&gt;Open a command window; navigate to the extracted folder and at the command prompt run the following commands&lt;/li&gt;&lt;ul&gt;&lt;li&gt;ruby dk.rb init&lt;/li&gt;&lt;li&gt;ruby dk.rb install&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Install Ansicon for Cucumber coloured output&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Visit: &lt;a href="http://adoxa.110mb.com/ansicon" target="_blank"&gt;http://adoxa.110mb.com/ansicon&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Download and extract ANSICON 1.40&lt;/li&gt;&lt;li&gt;Open a command prompt and navigate to the extracted folder; then navigate to the folder matching your machine x86/x64&lt;/li&gt;&lt;li&gt;At the command prompt run ansicon.exe -i&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Install Cucumber version=0.10.6&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;At the command prompt run the following commands&lt;/li&gt;&lt;li&gt;gem install cucumber --version=0.10.6&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Install Rake&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;At the command prompt run the following command&lt;/li&gt;&lt;li&gt;gem install rake --version=0.9.2&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Install Capybara&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;At the command prompt run the following command&lt;/li&gt;&lt;li&gt;gem install capybara --version=0.4.0&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Install RSpec&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;At the command prompt run the following command&lt;/li&gt;&lt;li&gt;gem install rspec --version=2.6.0&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Verify&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;At the command prompt run the following command&lt;/li&gt;&lt;li&gt;gem list&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;You should now have a gem list resembling the list below; if you are missing a few dont panic simply follow the same process and install each gem.&lt;br /&gt;&lt;br /&gt;If you have gems with higher version numbers than what I have displayed here; simply perform the following:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Uninstall Gem&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;At the command prompt run the following command&lt;/li&gt;&lt;li&gt;gem &lt;name&gt; uninstall --version=#gem version number#&lt;version&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;For your consideration&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Here are a few things you should consider with a Cucumber/Ruby based approach to acceptance testing for .NET web applications when not using the DLR.  &lt;br /&gt;&lt;br /&gt;&lt;i&gt;Step Definition Styles;  From the RSpec Book&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;In order to test interactions with a web based system we have three styles of step definition.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Automated Browser: Access the entire Rails MVC stack in a real&lt;br /&gt;web browser by driving interactions with the Webrat API and its&lt;br /&gt;support for piggybacking on Selenium. This style is fully integrated&lt;br /&gt;but is the slowest to run and can be challenging to maintain.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Simulated Browser: Access the entire MVC stack using Webrat,&lt;br /&gt;a DSL for interacting with web applications. This style provides a&lt;br /&gt;reliable level of integration while remaining fast enough for general&lt;br /&gt;use, but it doesn’t exercise JavaScript.&lt;/li&gt;&lt;li&gt;Direct Model Access: Access ActiveRecord models directly, bypass-&lt;br /&gt;ing routing, controllers, and views. This is the fastest but least&lt;br /&gt;integrated style.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Unfortunately using Cucumber/Ruby you are unable to do DMA;  for obvious reasons; the code base under test is in C# not Ruby.  This is an issue when the number of tests grows quite large and performance/speed of execution becomes an issue; we ideally would like to use DMA as its faster to execute.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Test data&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;For the same reasons test data is an issue. There are a few approaches to getting test data into acceptance tests:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Write automated tests which add data to the database via an administration tool; embedding the test data into automated cucumber stories&lt;/li&gt;&lt;li&gt;Running database scripts to populate the database&lt;/li&gt;&lt;li&gt;Adding data to the database or to an in-memory database directly via code; DMA&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The first two options have issues; automating the process of adding data via an admin tool is powerful;  you can perform clean-up and it can be automated; but is obviously slow.  Running scripts is error prone; and difficult to clean up; leaving us DMA which is both simple and can be automated as a series of step definitions.&lt;br /&gt;&lt;br /&gt;Cucumber on the DLR would obviously resolve these issues; so if you are able to get the DLR onto your stack I would absolutely go with that option.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Gem List&lt;/b&gt;&lt;br /&gt;archive-tar-minitar (0.5.2)&lt;br /&gt;builder (3.0.0)&lt;br /&gt;capybara (0.4.0)&lt;br /&gt;celerity (0.8.9)&lt;br /&gt;childprocess (0.1.7)&lt;br /&gt;columnize (0.3.3)&lt;br /&gt;configuration (1.2.0)&lt;br /&gt;cucumber (0.10.6)&lt;br /&gt;culerity (0.2.15)&lt;br /&gt;diff-lcs (1.1.2)&lt;br /&gt;ffi (0.6.3 x86-mingw32)&lt;br /&gt;gherkin (2.4.0 x86-mingw32)&lt;br /&gt;json (1.5.2, 1.4.6)&lt;br /&gt;json_pure (1.5.2)&lt;br /&gt;launchy (0.4.0)&lt;br /&gt;linecache (0.45)&lt;br /&gt;mime-types (1.16)&lt;br /&gt;nokogiri (1.4.4.1 x86-mingw32)&lt;br /&gt;rack (1.3.0)&lt;br /&gt;rack-test (0.6.0)&lt;br /&gt;rake (0.9.2)&lt;br /&gt;relish (0.4.0)&lt;br /&gt;require_relative (1.0.1)&lt;br /&gt;rest-client (1.6.3)&lt;br /&gt;rspec (2.6.0)&lt;br /&gt;rspec-core (2.6.4)&lt;br /&gt;rspec-expectations (2.6.0)&lt;br /&gt;rspec-mocks (2.6.0)&lt;br /&gt;ruby-debug-base (0.10.5.jb2 mswin32)&lt;br /&gt;ruby-debug-ide (0.4.17.beta3)&lt;br /&gt;rubyzip (0.9.4)&lt;br /&gt;selenium-webdriver (0.1.2)&lt;br /&gt;term-ansicolor (1.0.5)&lt;br /&gt;xpath (0.1.4)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-8201648858143023257?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/8201648858143023257/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/07/cucumber-on-windows.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/8201648858143023257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/8201648858143023257'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/07/cucumber-on-windows.html' title='Cucumber on Windows'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-1260245464423643636</id><published>2011-06-22T20:49:00.017+01:00</published><updated>2011-07-29T19:32:13.661+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Appharbor'/><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><title type='text'>git push appharbor who the master</title><content type='html'>&lt;a href="http://appharbor.com" target="_blank"&gt;&lt;img height="90" width="400" src="http://4.bp.blogspot.com/-4bXGkFJeLLE/TgGcK4ghbRI/AAAAAAAAAF0/GYSZyTW4ZoE/s400/appharbor.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A bold statement ;)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://appharbor.com" target="_blank"&gt;AppHarbor&lt;/a&gt; is a cloud based hosting platform for .net applications not to dissimilar to &lt;a href="http://www.heroku.com/" target="_blank"&gt;Herouku&lt;/a&gt;; the Ruby on Rails based hosting platform.  What interests me about AppHarbor is its integration with Git and its simple deployment process; oh and prices currently start at free :).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Features&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Push and deploy new builds in seconds&lt;/li&gt;&lt;li&gt;Git-enabled continuous development environment&lt;/li&gt;&lt;li&gt;Run specifications before release; currently only supports NUnit&lt;/li&gt;&lt;li&gt;SQL Server/MySQL database hosting&lt;/li&gt;&lt;li&gt;Single click rollback via web based administration tool &lt;/li&gt;&lt;li&gt;Manage certificates, hostnames from web based administration tool&lt;/li&gt;&lt;li&gt;Can scale&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Setup&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;AppHarbor setup and code deployment is pretty straightforward;  &lt;a href="http://support.appharbor.com/kb/getting-started/deploying-your-first-application" target="_blank"&gt;information on how to do this can be found here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Below is a list of issues I had during setup/deployment because I was to lazy to read the documentation properly;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Ensure you have setup ssh&lt;/li&gt;&lt;li&gt;Name your solution file appharbor; (annoying)&lt;/li&gt;&lt;li&gt;Initialise your Git repository where the solution file for your project lives; (you only want to deploy the source code; not everything else associated with your project&lt;/li&gt;&lt;li&gt;Ensure all your views have the their properties set correctly  (this was required for my views as they are Spark Views; not sure if this is the case for all view engines)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Build Action = Content &lt;br /&gt;&lt;li&gt;Copy to Output Directory = Copy always &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;&lt;b&gt;Final thoughts&lt;/b&gt; &lt;/p&gt;&lt;p&gt;AppHarbor; works well; the deployment process is seamless; rolling back a release is also simple. There are a few issues I would like to see resolved before I would consider paying for such a service: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strike&gt;No support for object databases.&lt;/strike&gt;&lt;/li&gt;&lt;li&gt;Unable to run MSpec specifications&lt;/li&gt;&lt;li&gt;Your solution file has to be named appharbor; why; if I decide to use AppHarbor again for another project I will have multiple solutions with the same name&lt;/li&gt;&lt;li&gt;Better documentation; specifically info on how to push a subset of my codebase to AppHarbor from GitHub&lt;/li&gt;&lt;li&gt;No support for database migrations; currently a manual process&lt;/li&gt;&lt;li&gt;Restore of database and import of data into the AppHarbor database is painful&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Luckily most of these features are quite high on the AppHarbor community driven &lt;a href ="http://feedback.appharbor.com/forums/95687-general"&gt;TODO&lt;/a&gt; list; and will hopefully be resolved.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-1260245464423643636?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/1260245464423643636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/06/git-push-appharbor-who-master.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/1260245464423643636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/1260245464423643636'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/06/git-push-appharbor-who-master.html' title='git push appharbor who the master'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-4bXGkFJeLLE/TgGcK4ghbRI/AAAAAAAAAF0/GYSZyTW4ZoE/s72-c/appharbor.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-2311155647536019629</id><published>2011-05-27T11:54:00.024+01:00</published><updated>2011-05-30T22:24:54.407+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Continuous Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Ju.Ju.'/><category scheme='http://www.blogger.com/atom/ns#' term='Behaviour Driven Development'/><title type='text'>The Oneness of ju.ju.</title><content type='html'>&lt;h3&gt;Introduction&lt;/h3&gt;&lt;br /&gt;Continuous testing is a TDD process whereby tests/specifications are automated to run when changes to files are observed on a project under development.  This allows the developer to focus on developing software by minimising context switching providing a rapid feedback loop.&lt;br /&gt;&lt;br /&gt;ju.ju. is a continuous testing tool with a difference; it will work with any combination of build, specification, notification tools.  ju.ju. simply watches a directory for file changes;  when a change is observed; an event is fired which calls a batch file.  The batch file can perform a build, run specifications and notify you of build/specification run state.&lt;br /&gt;&lt;br /&gt;How you build, run specifications or send notifications for your project is of no concern to ju.ju..  You could be using Rake; PSake; Fake; MSpec, Nunit, Xunit; Growl or Snarl or some other known; or yet to be created tool; it makes no difference.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Benefits over similar tools&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Configure multiple projects using different build/specification tools;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Configure your unit level specifications to use MSpec and your integration tests to use NUnit.&lt;/li&gt;&lt;li&gt;Useful when migrating from one specification tool to another&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Easily switch between different projects; for applications spanning multiple projects&lt;/li&gt;&lt;li&gt;Simple to use Gui allows you to configure file types to watch and exclude projects sub folders whilst developing your application&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Go Git it: &lt;/h3&gt;&lt;br /&gt;&lt;a href="https://github.com/AndrewKeig/ju.ju."&gt;https://github.com/AndrewKeig/ju.ju.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is a dummy project to test it with&lt;br /&gt;&lt;a href="https://github.com/AndrewKeig/SpaceJungle"&gt;https://github.com/AndrewKeig/SpaceJungle&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;ju.ju. Installation&lt;/h3&gt;&lt;br /&gt;Unzip this project to a drive near you.  Place the contents of  ju.ju.\release into c:\juju\.  This folder should contain the following files;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-_gd_RcAQlqo/Td6OTU-L2yI/AAAAAAAAAE4/8F7FoY8tfOU/s1600/jujuContents.png" imageanchor="1"&gt;&lt;img border="0" height="180" src="http://1.bp.blogspot.com/-_gd_RcAQlqo/Td6OTU-L2yI/AAAAAAAAAE4/8F7FoY8tfOU/s400/jujuContents.png" width="261" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;juju.gui.exe.config&lt;/h3&gt;&lt;br /&gt;The file juju.gui.exe.config has a key in it which can be configured; although will work as is; this key is the location of the ju.ju. projects folder.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/993555.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;juju.projects&lt;/h3&gt;&lt;br /&gt;ju.ju. uses a JSON based configuration file to represent a ju.ju. project; all project files are located in this folder.  A ju.ju. file has the following key/values which require configuration:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/993559.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Id&lt;/b&gt;, project identifier&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Name&lt;/b&gt;, the name of the project; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Description&lt;/b&gt;, a description of the project&lt;br /&gt;&lt;br /&gt;&lt;b&gt;DirectoriesToExclude&lt;/b&gt;, a comma seperated list of directories inside the folder being watched which will not be watched &lt;br /&gt;&lt;br /&gt;&lt;b&gt;DirectoryToWatch&lt;/b&gt;, the path to your projects solution&lt;br /&gt;&lt;br /&gt;&lt;b&gt;BatchFile&lt;/b&gt;, the batch file called by ju.ju. when a file change has been observed&lt;br /&gt;&lt;br /&gt;&lt;b&gt;InternalBufferSize&lt;/b&gt;, the internal buffer size for a process; can require a large value to enable ju.ju. to detect changes in a large file base; see FileSystemWatcher&lt;br /&gt;&lt;br /&gt;&lt;b&gt;FileTypesToWatch&lt;/b&gt;, the file types ju.ju. will watch; a comma seperated list of file extensions&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Delay&lt;/b&gt;, is the delay in seconds between responding to a file save; a single file save generally results in multiple events firing; so the aim is to try and avoid responding to all and treat them as one; see FileSystemWatcher&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;juju.runners&lt;/h3&gt;&lt;br /&gt;This folder contains batch files which projects can be configured to use.  These batch files are executed when a file change has been observed.&lt;br /&gt;&lt;br /&gt;Below is an example batch file; this file has been configured to build, run specifications and perform notification. The below batch file takes three arguments:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The build file&lt;/li&gt;&lt;li&gt;The specification/test runner file&lt;/li&gt;&lt;li&gt;The project name&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/993570.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Example build file&lt;/h3&gt;&lt;br /&gt;Below is an example build file; which uses MSBuild:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/993571.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Example specification/test runner file&lt;/h3&gt;&lt;br /&gt;Below is an example specificaiton file; which uses MSpec:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/993573.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;juju.notifiers&lt;/h3&gt;&lt;br /&gt;Below is an example notification file; which uses Growl&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/993575.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;ju.ju. does not require you use a notifier; but if you would like notification; install Growl.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.growlforwindows.com/gfw/"&gt;http://www.growlforwindows.com/gfw/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Working with ju.ju.&lt;/h3&gt;&lt;br /&gt;Firing up juju.gui.exe opens up the following two windows:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ju.ju. main window&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This window allows you to configure and protect your projects.  There are two sections; the left side is a ju.ju. config file editor; the details of the file have already been outlined in section above headed juju.projects; the right side allows you to select a project in order to edit it or protect it.&lt;br /&gt;&lt;br /&gt;&lt;img height="337" src="http://3.bp.blogspot.com/-i_tnNzGRuyQ/Td6PGuiQL0I/AAAAAAAAAFA/VuiXQcbyynM/s640/jujuGui.png" width="640" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ju.ju. output window&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This window displays the output of the batch file which is executed when a file change has been observed.&lt;br /&gt;&lt;br /&gt;&lt;img height="364" src="http://4.bp.blogspot.com/-WAkRHTbnPrg/Td6PkTMmkcI/AAAAAAAAAFY/Tgq7_E6f5lw/s640/jujuOutputWindow.png" width="640" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Editing a ju.ju. config file&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Select a project on the right hand side; then click edit to make changes to a ju.ju. config file; click save to persist these.&lt;br /&gt;&lt;br /&gt;&lt;img height="339" src="http://2.bp.blogspot.com/-1n5ApjFyAuI/Td6POpj3zXI/AAAAAAAAAFI/3ZdFBD12IXc/s640/jujuGuiEdit.png" width="640" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Protecting a project&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Select a project on the right hand side; then click protect to start protecting a project.&lt;br /&gt;&lt;br /&gt;&lt;img height="339" src="http://1.bp.blogspot.com/-48FojzZo0yI/Td6PcgvixJI/AAAAAAAAAFQ/8wGq-tGiYaY/s640/jujuGuiProtected.png" width="640" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Output window displaying build and specification run.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img height="364" src="http://2.bp.blogspot.com/-6qzyXBTrVxA/Td6PqjqfwXI/AAAAAAAAAFg/kRsd4KKVzHs/s640/jujuOutputWindowWithSpecRunner.png" width="640" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Growl notifying user of changes&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img height="360" src="http://4.bp.blogspot.com/-kuWYIboa2r8/Td6Pyqq9QeI/AAAAAAAAAFo/NgTqU4GtfNM/s640/VisualStudioUpdateWithGrowlNotification.png" width="640" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Future Improvements&lt;/h3&gt;&lt;br /&gt;&lt;b&gt;UI enhancements&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Directories to exclude should be changed to a multi select listbox; containing all directories under the directory being watched.&lt;/li&gt;&lt;li&gt;File types to watch; should be changed to a multi select listbox of file extensions&lt;/li&gt;&lt;li&gt;Allow user to add a new config file&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Performance Improvements&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Intelligent specification runs; ju.ju. runs all specifications for a file change&lt;/li&gt;&lt;ul&gt;&lt;li&gt;only run the specifications in the specification file changed&lt;/li&gt;&lt;li&gt;only run the relevant specifications for the subject under specification&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-2311155647536019629?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/2311155647536019629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/05/oneness-of-juju.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/2311155647536019629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/2311155647536019629'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/05/oneness-of-juju.html' title='The Oneness of ju.ju.'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-_gd_RcAQlqo/Td6OTU-L2yI/AAAAAAAAAE4/8F7FoY8tfOU/s72-c/jujuContents.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-1284707495075799039</id><published>2011-04-20T17:03:00.007+01:00</published><updated>2011-04-20T17:22:12.430+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='specification.patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='MSpec'/><category scheme='http://www.blogger.com/atom/ns#' term='SpecFlow'/><category scheme='http://www.blogger.com/atom/ns#' term='Behaviour Driven Development'/><title type='text'>Behaviour Driven Development with MSpec, SpecFlow, and Friends - Iteration 1</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;b&gt;In this series&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec_25.html"&gt;Iteration 0&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/04/behaviour-driven-development-with-mspec.html"&gt;Iteration 1&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;In our previous post we decided to select the simplest slice of functionality from our list of stories.  &lt;br /&gt;&lt;br /&gt;In order to get us started I have done the following:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Created an empty ASP.Net MVC 3 solution&lt;/li&gt;&lt;li&gt;Created an empty class project - Specifications&lt;/li&gt;&lt;li&gt;Created an empty class project - Stories&lt;/li&gt;&lt;li&gt;Added the following packages to the relevant project:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/machine/machine.specifications" target="_blank"&gt;MSpec&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://specflow.org/" target="_blank"&gt;SpecFlow&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/specification.patterns" target="_blank"&gt;specification.patterns&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://seleniumhq.org/" target="_blank"&gt;Selenium&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/moq/" target="_blank"&gt;Moq&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://structuremap.net/structuremap/" target="_blank"&gt;Structuremap&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.nunit.org/" target="_blank"&gt;NUnit&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sparkviewengine.com/" target="_blank"&gt;Spark View Engine&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Added a Specflow and Selenium base class for our SpecFlow feature files&lt;/li&gt;&lt;li&gt;Bootstrapped StructureMap for DI via the new DependencyResolver&lt;/li&gt;&lt;li&gt;Setup Spark View Engine&lt;/li&gt;&lt;li&gt;Setup Selenium server and Firefox plugin&lt;/li&gt;&lt;li&gt;Setup source control with Git&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Our design for devtracks is below; this design has been split up into various Spark View Engine partials; and a page.&lt;br /&gt;&lt;br /&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-Bq0zhMjytYg/TaYn40PiJPI/AAAAAAAAADs/m5NbqfBgxT4/s1600/homepage.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Creating a SpecFlow feature: Navigate to Homepage&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/907579.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Copy the above feature/scenario into a SpecFlow feature file; the scenarios in this feature file are acceptance tests; each Given/When/Then step within a scenario should map to a method.  Start the Selenium web server; and then run your favourite test runner against this feature file.&lt;br /&gt;&lt;br /&gt;Your test runner should report that the tests have been ignored; and will generate some SpecFlow skeleton code; a method for each Given/When/Then step.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Missing steps when running the Navigate to Homepage feature&lt;/b&gt; &lt;img border="0" src="http://3.bp.blogspot.com/-83tbN5IbMrk/TaYiVe1WSmI/AAAAAAAAADg/QyqjPj2h3Ig/s1600/homepage_story_runner.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Grab and edit this generated code and paste it into a new class file.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Edited SpecFlow skeleton code&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/918187.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Now run your favourite test runner against this feature file; the test runner will now declare the tests ignored; the tests have been skipped because the steps have not been implemented; they are set to pending.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pending steps when running the Navigate to Homepage feature&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-AdYtVDzuSzk/TaYuKgxfrgI/AAAAAAAAADw/WM2CLoEYx-0/s1600/homepage_story_runner_step_2.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Driving out the unit level code using MSpec&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We now have a running ASP.Net MVC site with a single spark view. the view contains our new design.  We have created a SpecFlow feature file;  all steps are set to pending.  We now need to get the first SpecFlow step passing. In order to do this we will need to implement some code.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;SessionController specification using MSpec&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/919034.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;If you run these specifications through; they will all be ignored and require implementation.&lt;br /&gt;&lt;br /&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-7hN26F80t7A/TaafCrkUUwI/AAAAAAAAAEQ/JbtFMHlhqbI/s1600/homepage_spec_runner_1.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Lets complete the specification.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/919044.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Lets create a new ASP.Net MVC SessionController.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/931824.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Now re-run the specifications to watch them pass.&lt;br /&gt;&lt;br /&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-3TCTK6wOXR8/TaafCtjXkwI/AAAAAAAAAEU/xM4SYJWHyA0/s1600/homepage_spec_runner_2.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If we open our site in a browser; open the Selenium IDE Firefox plugin and perform the following:&lt;br /&gt;&lt;br /&gt;1. Click the logo&lt;br /&gt;2. Mouseover the logo and right click&lt;br /&gt;3. Select VerifyText img[@alt='devtracks']&lt;br /&gt;&lt;br /&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-lkolrSOrNvo/TaaclQplgpI/AAAAAAAAAEI/Wa_xBRaruaM/s1600/selenium_remote.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Fill in the details with the following:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/918989.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;Now re-run the acceptance tests and watch those pass.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-D5C3MbpfXbQ/Ta79aJUy9tI/AAAAAAAAAEw/O4rlJHnCEvE/s1600/runnerComplete.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="473" src="http://4.bp.blogspot.com/-D5C3MbpfXbQ/Ta79aJUy9tI/AAAAAAAAAEw/O4rlJHnCEvE/s640/runnerComplete.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Feature Complete!&lt;br /&gt;&lt;br /&gt;Here's a series of screencasts for this feature; warts and all:&lt;br /&gt;&lt;br /&gt;&lt;iframe frameborder="0" height="274" src="http://www.screenr.com/embed/oqa" width="450"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;iframe src="http://www.screenr.com/embed/xL5" width="450" height="274" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;iframe src="http://www.screenr.com/embed/EL5" width="450" height="274" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-1284707495075799039?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/1284707495075799039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/04/behaviour-driven-development-with-mspec.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/1284707495075799039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/1284707495075799039'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/04/behaviour-driven-development-with-mspec.html' title='Behaviour Driven Development with MSpec, SpecFlow, and Friends - Iteration 1'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-Bq0zhMjytYg/TaYn40PiJPI/AAAAAAAAADs/m5NbqfBgxT4/s72-c/homepage.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-2465209474386535773</id><published>2011-04-01T14:48:00.004+01:00</published><updated>2011-04-05T11:35:03.834+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MongoDB'/><category scheme='http://www.blogger.com/atom/ns#' term='Cartoon'/><category scheme='http://www.blogger.com/atom/ns#' term='NoSQL'/><title type='text'>MongoDB is web scale</title><content type='html'>&lt;object width="504" height="312"&gt;&lt;param name="movie" value="http://www.xtranormal.com/site_media/players/jwplayer.swf" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="flashvars"value="height=312&amp;width=504&amp;allowscriptaccess=always&amp;allowfullscreen=true&amp;skin=http://www.xtranormal.com%2Fsite_media%2Fplayers%2Fjw_player_v54%2Fxn.xml&amp;file=http://newvideos.xtranormal.com/web_final_lo/574b3910-afc9-11df-914b-003048d69c21_27_web_final_lo_web_finallo-flv.flv&amp;image=http://newvideos.xtranormal.com/web_final_lo/574b3910-afc9-11df-914b-003048d69c21_27_web_final_lo_poster.jpg&amp;link=http://www.xtranormal.com/watch/6995033&amp;title=Mongo DB is web scale&amp;author=gar1t&amp;date=Aug. 24, 2010&amp;plugins=gapro%2Cfbit-1%2Ctweetit-1%2Cviral-2&amp;gapro.accountid=UA-5134028-2"/&gt;&lt;embed src="http://www.xtranormal.com/site_media/players/jw_player_v54/player.swf" height="312" width="504" allowscriptaccess="always" allowfullscreen="true" flashvars="skin=http://www.xtranormal.com%2Fsite_media%2Fplayers%2Fjw_player_v54%2Fxn.xml&amp;file=http://newvideos.xtranormal.com/web_final_lo/574b3910-afc9-11df-914b-003048d69c21_27_web_final_lo_web_finallo-flv.flv&amp;image=http://newvideos.xtranormal.com/web_final_lo/574b3910-afc9-11df-914b-003048d69c21_27_web_final_lo_poster.jpg&amp;link=http://www.xtranormal.com/watch/6995033&amp;title=Mongo DB is web scale&amp;author=gar1t&amp;date=Aug. 24, 2010&amp;plugins=gapro%2Cfbit-1%2Ctweetit-1%2Cviral-2&amp;gapro.accountid=UA-5134028-2" /&gt;&lt;/embed&gt;&lt;/object&gt;&lt;object width="1" height="1"&gt;&lt;param name="movie" value="http://www.xtranormal.com/site_media/players/embedded-xnl-stats.swf" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;embed src="http://www.xtranormal.com/site_media/players/embedded-xnl-stats.swf" width="1" height="1" allowscriptaccess="always"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-2465209474386535773?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/2465209474386535773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/04/mongo-db-is-web-scale.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/2465209474386535773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/2465209474386535773'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/04/mongo-db-is-web-scale.html' title='MongoDB is web scale'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-4751254205330527356</id><published>2011-03-31T01:27:00.002+01:00</published><updated>2011-04-05T11:35:31.839+01:00</updated><title type='text'>Programmer Personality</title><content type='html'>Will introduce this as part of my interview process..&lt;br /&gt;&lt;br /&gt;&lt;a href="http://start.sbastn.com"&gt;via Sebastian Hermida&lt;/a&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://start.sbastn.com/static/images/programmer-personality/programmer-personality.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="2912" width="500" src="http://start.sbastn.com/static/images/programmer-personality/programmer-personality.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-4751254205330527356?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/4751254205330527356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/03/programmer-personality.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/4751254205330527356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/4751254205330527356'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/03/programmer-personality.html' title='Programmer Personality'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-9081212533760388984</id><published>2011-03-29T16:44:00.010+01:00</published><updated>2011-04-20T17:18:39.783+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='specification.patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='MSpec'/><category scheme='http://www.blogger.com/atom/ns#' term='SpecFlow'/><category scheme='http://www.blogger.com/atom/ns#' term='Behaviour Driven Development'/><title type='text'>Behaviour Driven Development with MSpec, SpecFlow, and Friends - Iteration 0</title><content type='html'>&lt;b&gt;In this series&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec_25.html"&gt;Iteration 0&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/04/behaviour-driven-development-with-mspec.html"&gt;Iteration 1&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Introducing devtracks&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;devtracks aims to deliver software development videos focusing mainly on the open source .net space. The videos are a combination of software development presentations and tutorials which are already freely available but scattered around the net on various sites.  devtracks aims to bring much of this content under one site.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Ubiquitous language&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"With a UBIQUITOUS LANGUAGE, the model is not a design artifact.  It becomes integral to everything the developers and domain experts do to together.  The LANGUAGE carries knowledge in a dynamic form.  Discussion in the LANGUAGE brings to life the meaning behind the diagram and code."&lt;br /&gt;Eric Evans&lt;/div&gt;&lt;br /&gt;Lets define our ubiquitous language for devtracks; devtracks will use the language of software development conferences:&lt;br /&gt;&lt;br /&gt;A software development conference has:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Session - a single presentation/tutorial&lt;/li&gt;&lt;li&gt;Track - a topic/category relating to software development; contains multiple sessions&lt;/li&gt;&lt;li&gt;Speaker - delivers a session&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Stories&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Lets start our story creation process by defining the stories and their conditions of acceptance.&lt;br /&gt;&lt;br /&gt;When writing your conditions of acceptance; ensure you limit the number of domains in a single scenario in order to avoid writing brittle tests.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Read this article by Dan North: &lt;a href=”http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/”&gt;Whose domain is it anyway?&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/891506.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Where to start? A Walking Skeleton&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Over the years I have seen a few different approaches to getting a project up and running.  I have recently settled on the idea of a 'Walking Skeleton'.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"A Walking Skeleton is a tiny implementation of the system that performs a small end-to-end function."&lt;br /&gt;Alistair Cockburn&lt;/div&gt;&lt;br /&gt;The idea of a walking skeleton is to select the simplest story available and implement this from the 'outside-in' using BDD.  Our simplest story is: 'Navigate to Homepage'. We will drive out this feature putting in place various bits and pieces as we go:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create an ASP.Net MVC 3 empty solution&lt;/li&gt;&lt;li&gt;Setup folder structures/projects if required&lt;/li&gt;&lt;li&gt;Tool selection; see list below; NuGet has made this rather simple:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/machine/machine.specifications" target="_blank"&gt;MSpec&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://specflow.org/" target="_blank"&gt;SpecFlow&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/specification.patterns" target="_blank"&gt;specification.patterns&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://seleniumhq.org" target="_blank"&gt;Selenium&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/moq/" target="_blank"&gt;Moq&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://structuremap.net/structuremap/" target="_blank"&gt;Structuremap&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.nunit.org/" target="_blank"&gt;NUnit&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://nhforge.org/Default.aspx" target="_blank"&gt;NHibernate 3&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://fluentnhibernate.org/" target="_blank"&gt;Fluent NHibernate&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sparkviewengine.com/" target="_blank"&gt;Spark View Engine&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Specflow and Selenium infrastructure&lt;/li&gt;&lt;li&gt;Bootstrap StructureMap&lt;/li&gt;&lt;li&gt;Setup StructureMap registry&lt;/li&gt;&lt;li&gt;Source control setup with Git&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;What comes first BDD or DDD?  Well; if you are a single developer or a pair; this is not an issue; with a very simple domain model use BDD to drive out the domain; its probable you will not need a domain model; some simple DTOs/Information Holders will suffice.  If you are more than a single pair?  with a complex domain model; you run the danger of duplicating effort when driving out the domain model; so keeping things as agile as possible; consider the following:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Some minimal up-front design; drive out the model on paper first&lt;/li&gt;&lt;li&gt;Schedule the execution of stories so that you minimise duplication of effort&lt;/li&gt;&lt;li&gt;Introduce dependencies on a story that will drive out an aggregate root&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Iteration 1&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Lets Begin!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-9081212533760388984?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/9081212533760388984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec_25.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/9081212533760388984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/9081212533760388984'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec_25.html' title='Behaviour Driven Development with MSpec, SpecFlow, and Friends - Iteration 0'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-7525534119447705943</id><published>2011-03-26T08:08:00.059Z</published><updated>2011-04-20T17:08:56.666+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><category scheme='http://www.blogger.com/atom/ns#' term='specification.patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='MSpec'/><category scheme='http://www.blogger.com/atom/ns#' term='Behaviour Driven Development'/><title type='text'>specification.patterns</title><content type='html'>&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;specification.patterns is a small C# framework which helps developers focus on design rather than testing when specifying the subject under specification (SUS) and its messages/communication between its immediate collaborators. &lt;br /&gt;&lt;br /&gt;This framework draws on the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Responsibility Driven Development&lt;/li&gt;&lt;li&gt;XUnit Patterns&lt;/li&gt;&lt;li&gt;Domain Driven Design&lt;/li&gt;&lt;li&gt;Behaviour Driven Development&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Git it here&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/AndrewKeig/specification.patterns" target="_blank"&gt;https://github.com/AndrewKeig/specification.patterns&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Behaviour Driven Development at the unit level has solved the problem of documenting an objects behaviour; but we are still partially focused on testing when it comes to writing specifications. &lt;br /&gt;&lt;br /&gt;The context contains the following important but generally overlooked elements that document quite a lot about the design of the object/system being written; these elements include:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the subject under specification&lt;/li&gt;&lt;ul&gt;&lt;li&gt;its direct inputs&lt;/li&gt;&lt;li&gt;its direct output&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;the subjects collaborators&lt;/li&gt;&lt;ul&gt;&lt;li&gt;expectations set on collaborator&lt;/li&gt;&lt;li&gt;indirect inputs to collaborator&lt;/li&gt;&lt;li&gt;indirect output from collaborator&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Inputs &amp; Outputs&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"A running Object-Oriented (OO) program is a web of objects that collaborate by sending messages to each other."&lt;br /&gt;{sfreeman, npryce, tmackinnon, jwalnes}&lt;/div&gt;&lt;br /&gt;When we build the subject under specification we refer to it’s inputs/outputs in a test-centric way; we use words like expected output and actual output;  this is the language of test after development.&lt;br /&gt;&lt;br /&gt;The messages passed between objects are critical to good OOD.  It is important to distinguish between the types of communication (messages) that are passed between objects.   &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Collaborators&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"Mock Objects is misnamed. It is really a technique for identifying types in a system based on the roles that objects play."&lt;br /&gt;{sfreeman, npryce, tmackinnon, jwalnes}&lt;/div&gt;&lt;br /&gt;Mocking collaborators for a subject under specification is a design activity;  you are discovering other roles and collaborators; 'Interface Discovery' whilst designing/developing a feature.  To 'mock’ is the language of test after development.&lt;br /&gt;&lt;br /&gt;We care about the relationship between objects when we are designing software so it makes sense that within our specifications we make it clear to the reader of a specification what contributors are important to a given behaviour specified and what are simply dummy objects.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TDD/BDD is a design activity?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Would it not be useful to use the language of design when designing the subject under specification and the communication between collaborators.  Here are a few languages we could use:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Responsibility Driven Development&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Roles&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Information Holder&lt;/li&gt;&lt;li&gt;Structurer&lt;/li&gt;&lt;li&gt;Coordinator&lt;/li&gt;&lt;li&gt;Controller&lt;/li&gt;&lt;li&gt;Interfacer&lt;/li&gt;&lt;li&gt;Service Provider&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Responsibilities&lt;/li&gt;&lt;li&gt;Collaborators&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Domain Driven Design&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Aggregates&lt;/li&gt;&lt;li&gt;Entities&lt;/li&gt;&lt;li&gt;Value Objects&lt;/li&gt;&lt;li&gt;Services&lt;/li&gt;&lt;li&gt;Repositories&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;xunit patterns&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Indirect Inputs (input for a contributor)&lt;/li&gt;&lt;li&gt;Indirect Output (output of a contributor)&lt;/li&gt;&lt;li&gt;Direct Inputs (input for a subject under specification)&lt;/li&gt;&lt;li&gt;Direct Output (output of a subject under specification)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Breaking flow&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When we use the builder pattern for creating inputs/outputs; creating these builders breaks flow.  &lt;br /&gt;&lt;br /&gt;Many developers prefer to use hard coded mocks over a mocking framework. Why side track yourself whilst designing an object with building a fake version of an object you are not currently designing?.  If you are designing an object and you feel a given piece of behaviour should be delegated to another object simply acknowledge its existence; move on; and design the object you are actually working on.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Introducing&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;specification.patterns is a framework for designing the subject under specification (SUS) and the communication between collaborators. It provides the following features: &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Focus on the design aspect of TDD/BDD&lt;/li&gt;&lt;li&gt;Introduces the language of OOD into your specification process&lt;/li&gt;&lt;li&gt;Plug-able roles/stereotypes based on various OOD/Specification methodologies&lt;/li&gt;&lt;li&gt;Clearly define the relationships between SUS and its collaborators&lt;/li&gt;&lt;li&gt;A generic message builder; helps maintain flow and enforces some basic DDD conventions&lt;/li&gt;&lt;li&gt;Automock trivial collaborators&lt;/li&gt;&lt;li&gt;Improves upon the specification as documentation concept&lt;/li&gt;&lt;li&gt;Improve readability at the context level&lt;/li&gt;&lt;li&gt;Assist those new to TDD/BDD interaction based testing&lt;/li&gt;&lt;li&gt;Reduces the noise in your specification context&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Example using MSpec:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/888139.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How it works&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The specification.patterns framework wraps the Moq framework and exposes the Subject on a base class. With this we can do the following:&lt;br /&gt;&lt;br /&gt;Create specific types of message for collaborating objects using a generic builder &lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/892509.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Define a relationship with the Subject and a collaborator that plays a roll in this specification&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/892512.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Set a message expectation for a collaborator&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/892515.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Run the specification&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/892517.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Verify that a message expectation was executed&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/892518.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Extending specification.patterns&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The language of design is constantly changing so the language elements (object builder) of specification.patterns is plugable to allow extension.  This is achieved by simply extending the base class StereoType and implementing from the interfaces below which define what the class can do:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;IHaveDependency&lt;/li&gt;&lt;li&gt;IHaveBehaviour&lt;/li&gt;&lt;li&gt;IHaveProperties&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/888146.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Warning - work in progress&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Version 0.1 of this project is very much alpha code; it works; I think; sort off :)  Basically I am throwing this out there to see if anyone sees any value in this and would like to contribute.  Feel free to tell me its bollocks; my wife already did; but balancing that my 3 year old son got really excited and ripped out two of the keys on my laptop;  it a’l come out in the wash..&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;References&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.100.2927&amp;rep=rep1&amp;type=pdf" target="_blank"&gt;Mock Roles, not Objects&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.co.uk/gp/product/0321503627/"  target="_blank"&gt;Growing Object-Oriented Software, Guided by Tests &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.co.uk/gp/product/0201379430/"  target="_blank"&gt;Object Design: Roles, Responsibilities and Collaborations&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.co.uk/dp/0131495054/"  target="_blank"&gt;xUnit Test Patterns: Refactoring Test Code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.co.uk/dp/0321125215"  target="_blank"&gt;Domain-driven Design: Tackling Complexity in the Heart of Software&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.infoq.com/presentations/Mock-Objects-Nat-Pryce-Steve-Freeman"  target="_blank"&gt;Mock Roles not Object States&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-7525534119447705943?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/7525534119447705943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/03/specificationpatterns-object-design.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/7525534119447705943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/7525534119447705943'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/03/specificationpatterns-object-design.html' title='specification.patterns'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-3120230280644212782</id><published>2011-03-04T16:37:00.020Z</published><updated>2011-12-07T07:56:12.826Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><category scheme='http://www.blogger.com/atom/ns#' term='NoSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Socket.IO'/><category scheme='http://www.blogger.com/atom/ns#' term='CouchDB'/><title type='text'>Node.Js with Socket.IO &amp; CouchDB</title><content type='html'>&lt;b&gt;This is a first attempt at doing something that appears useful with Node.Js.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;nosoco is a real-time football score video printer which pushes changes made in a CouchDB database to a web client via Node.Js/Socket.IO.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git that shit!&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Git me here&lt;br /&gt;&lt;span style="font-family:courier"&gt;git@github.com:AndrewKeig/nosoco.git&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Setup nosoco;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://nodejs.org/" target="_blank"&gt;Node.Js&lt;/a&gt;&lt;br /&gt;If you want some info on how to install Node.js -&gt;&lt;br /&gt;&lt;a href="http://airasoul.blogspot.com/2011/03/nodejs-installation.html"  target=”_blank”&gt;node.js Installation on a new Ubuntu installation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://couchdb.apache.org/" target="_blank"&gt;CouchDB&lt;/a&gt;&lt;br /&gt;If you want some info on how to install CouchDb -&gt;&lt;br /&gt;&lt;a href="http://airasoul.blogspot.com/2011/03/install-couchdb-and-couchapp-on-new.html"  target=”_blank”&gt;CouchDB installation on a new Ubuntu installation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://socket.io" target="_blank"&gt;Socket.IO&lt;/a&gt;&lt;br /&gt;Socket.IO aims to make realtime apps possible in every browser and mobile device, blurring the differences between the different transport mechanisms.  Socket.IO uses feature detection to decide if the connection will be established with WebSocket, AJAX long polling, etc based on browser capability.&lt;br /&gt;&lt;br /&gt;In order to setup Socket.IO simply clone the git:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier"&gt;git clone git://github.com/LearnBoost/Socket.IO-node.git socket.io --recursive &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This application requires a CouchDB database; as defined in couchdb.json with the following fields:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/864009.js?file=gistfile1.txt"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Hows it work&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Changes made to the CouchDB database are picked up on the couchdb _changes stream;   the node clip below attaches an Node event listener to the CouchDB change stream.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/864381.js?file=gistfile1.txt"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The node server will respond to this change event.  The steam only contains the ids of the items that have changed so we have to go back to the database to get the data.  We then construct a json doc and push these to the client.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/864391.js?file=gistfile1.txt"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;On the client side we have some javascript which responds to the change data stream; the socket connects to the node server and responds to events via the on method.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/864397.js?file=gistfile1.txt"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Run it&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Run the node server with the following command:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier"&gt;sudo node server.js&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now visit your browser; &lt;br /&gt;&lt;br /&gt;http://127.0.0.1:8080/Client.html&lt;br /&gt;&lt;br /&gt;In order to change the scores simply update the 'team_1_score' field using Futon or curl to push changes to the client...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-3120230280644212782?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/3120230280644212782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/03/nodejs-with-socketio-couchdb.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/3120230280644212782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/3120230280644212782'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/03/nodejs-with-socketio-couchdb.html' title='Node.Js with Socket.IO &amp; CouchDB'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-2467053629201352221</id><published>2011-03-01T10:57:00.021Z</published><updated>2011-05-27T11:20:00.985+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NoSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='CouchDB'/><title type='text'>CouchDB installation on a new Ubuntu installation</title><content type='html'>The below outlines the steps taken to install CouchDB on a new Ubuntu installation.&lt;br /&gt;&lt;br /&gt;Install CouchDB:&lt;br /&gt;&lt;span style="font-family: courier;"&gt;sudo aptitude install couchdb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Make sure CouchDB installation completed successfully; open a terminal and enter:&lt;br /&gt;&lt;span style="font-family: courier;"&gt;curl http://127.0.0.1:5984/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You should receieve JSON formatted welcome message:&lt;br /&gt;&lt;span style="font-family: courier;"&gt;{"couchdb":"Welcome","version":"0.10.0"}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CouchDB comes with a built-in web-based administration interface called Futon; visit this site:&lt;br /&gt;&lt;a href="http://127.0.0.1:5984/_utils/" target="_blank"&gt;http://127.0.0.1:5984/_utils/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The right side navigation has a tools section; click the 'Test Suite' link and run the tests to confirm all components were installed successfully.&lt;br /&gt;&lt;br /&gt;We done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-2467053629201352221?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/2467053629201352221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/03/install-couchdb-and-couchapp-on-new.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/2467053629201352221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/2467053629201352221'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/03/install-couchdb-and-couchapp-on-new.html' title='CouchDB installation on a new Ubuntu installation'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-4456381895327851306</id><published>2011-03-01T10:39:00.013Z</published><updated>2011-12-30T10:19:46.163Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>node.js Installation on a new Ubuntu installation</title><content type='html'>&lt;span style="font-weight:bold;"&gt;The below outlines the steps taken to install node.js on a new Ubuntu installation.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Install various libraries: including git:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier"&gt;sudo apt-get install g++ curl libssl-dev apache2-utils git-core&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Now download node.js using git:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier"&gt;git clone git://github.com/joyent/node.git&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;We are ready to install node.js; type the following:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier"&gt;cd node&lt;br /&gt;./configure&lt;br /&gt;make&lt;br /&gt;sudo make install&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Create a file called helloworld.js; stick the following into it:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier"&gt;gedit helloworld.js&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier"&gt;var http = require('http');&lt;br /&gt;http.createServer(function (req, res) {&lt;br /&gt;res.writeHead(200, {'Content-Type': 'text/plain'});&lt;br /&gt;res.end('Hello World\n');&lt;br /&gt;}).listen(8124, "127.0.0.1");&lt;br /&gt;console.log('Server running at http://127.0.0.1:8124/');&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;To run the hello world server:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier"&gt;node helloworld.js&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;In a browser visit:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;http://127.0.0.1:8124/&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;To install NPM:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;curl http://npmjs.org/install.sh | sudo sh&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-4456381895327851306?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/4456381895327851306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/03/nodejs-installation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/4456381895327851306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/4456381895327851306'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/03/nodejs-installation.html' title='node.js Installation on a new Ubuntu installation'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9168000460138974508.post-7678406263475243121</id><published>2011-02-05T15:32:00.008Z</published><updated>2011-04-20T17:18:47.763+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='specification.patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='MSpec'/><category scheme='http://www.blogger.com/atom/ns#' term='SpecFlow'/><category scheme='http://www.blogger.com/atom/ns#' term='Behaviour Driven Development'/><title type='text'>Behaviour Driven Development with MSpec, SpecFlow, and Friends</title><content type='html'>&lt;b&gt;In this series&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec_25.html"&gt;Iteration 0&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://airasoul.blogspot.com/2011/04/behaviour-driven-development-with-mspec.html"&gt;Iteration 1&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="font-color:#000000"&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"Behaviour Driven Development is a 2nd generation, outside-in, pull-based, multiple-stakeholder, multiple-scale, high-automation, Agile methodology. It describes a cycle of interactions with well-defined outputs, resulting in the delivery of working, tested software that matters."&lt;br /&gt;Dan North&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is the first in a series of posts; where I  implement a small web application using Behaviour Driven Development focusing on not just a specific tool; but more importantly outside-in development as a software methodology.&lt;br /&gt;&lt;br /&gt;The title of this series of posts has been adapted &lt;strike&gt;stolen&lt;/strike&gt; from the excellent book with a very similar name :) &lt;a href="http://www.amazon.co.uk/RSpec-Book-Behaviour-Development-Cucumber/dp/1934356379/ref=sr_1_1?ie=UTF8&amp;amp;qid=1297009841&amp;amp;sr=8-1%E2%80%9D" target="”_blank”"&gt;Behaviour Driven Development with RSpec, Cucumber, and Friends&lt;/a&gt;; go and buy this great book; when you’re done reading this.&lt;br /&gt;&lt;br /&gt;My main aims for this project are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;to drive the development process from the outside in&lt;/li&gt;&lt;li&gt;to document the systems behaviour; so that stakeholders at various levels can understand it&lt;/li&gt;&lt;li&gt;to increase flow and reduce noise during the specification process. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Behaviour driven development - an outside-in software development methodology&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"Behaviour driven development is an “outside-in” methodology. It starts at the outside by identifying business outcomes, and then drills down into the feature set that will achieve those outcomes. Each feature is captured as a “story”, which defines the scope of the feature along with its acceptance criteria."&lt;br /&gt;Dan North&lt;/div&gt;&lt;br /&gt;Most projects fail due to poor or a lack of communication at some level; Behaviour Driven Development aims to bridge these communication gaps by:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;using a ubiquitous shared/common language allowing stakeholders to communicate intelligently about the domain&lt;/li&gt;&lt;li&gt;driving out the real value in building a given feature&lt;/li&gt;&lt;li&gt;acceptance criteria for a scenario written in the Given/When/Then grammar as a definition of done&lt;/li&gt;&lt;li&gt;executable scenario and examples act as a living document of how the system works&lt;/li&gt;&lt;li&gt;obtaining feedback early on in the development process; showcase features developed during a given iteration&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Outside-in methodologies promote development according to stakeholder requirements in order to reduce the chance of building software that won’t be used.  It improves stakeholder communication and helps developers write the minimum amount of code in order to complete a story.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Behaviour driven development for scenarios&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"BDD tools come in two flavours - the "unit testing" flavour (such as NSpec and RSpec) and the higher level acceptance testing flavour such as Cucumber, JBehave or other clones of these tools. Cucumber's main goal is to involve more people and roles in acceptance testing and requirements, and make it an enjoyable (addictive) experience."&lt;br /&gt;Aslak Hellesøy&lt;/div&gt;&lt;br /&gt;At the scenario level our reasons for doing behaviour driven development are different to that at the unit level; we want to bridge the communications gap between all stake holders.  We agree on a ubiquitous language and a definition of done.  We write our scenarios/conditions of acceptance in conjunction with stakeholders in English.  We use a tool which allows us to execute a stories scenarios/conditions of acceptance as a series of tests.  A stories scenarios gives the developer a clearly defined start and end point as to where to start the development process and what is considered done for a given scenario.&lt;br /&gt;&lt;br /&gt;I will use SpecFlow to write stories/scenarios.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Behaviour driven development for unit level specifications&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"You write a specification that nails down a small aspect of behaviour in a concise, unambiguous, and executable form. It's that simple. Does that mean you write tests? No. It means you write specifications of what your code will have to do. It means you specify the behaviour of your code ahead of time."&lt;br /&gt;Dave Astels&lt;/div&gt;&lt;br /&gt;BDD at the unit level is basically about reaffirming good TDD practices; many people often refer to BDD at this level as ‘TDD done well’.  TDD is not really about testing at all; its a design process; wherby the developer specifies the behaviour to be written.&lt;br /&gt;&lt;br /&gt;At the unit level I am not concerned with writing specification in plain English; the issue is not really about communication with stakeholders outside of the development team; the reasons for doing BDD at this level are different to that at the acceptance specification level.  &lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:14px;font-style:italic"&gt;"While using and teaching agile practices like test-driven development (TDD) on projects in different environments, I kept coming across the same confusion and misunderstandings. Programmers wanted to know where to start, what to test and what not to test, how much to test in one go, what to call their tests, and how to understand why a test fails."&lt;br /&gt;Dan North&lt;/div&gt;&lt;br /&gt;We want to move away from the idea that we are testing the system; we are in fact documenting the system being developed by using examples; specification by example.  The verification and test coverage aspects are mearly side effects of this specification process; once we have completed this specification process we will be able to verify the systems behaviour and have test coverage.&lt;br /&gt;&lt;br /&gt;I will use MSpec to write unit level specifications&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Outside-in software development cycle&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The below diagram outlines the behaviour driven/outside-in approach to software development:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-1bQgES38LQU/TV5ZrQdW_ZI/AAAAAAAAACU/Da02S8MF7Co/s1600/cycle.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-1bQgES38LQU/TV5ZrQdW_ZI/AAAAAAAAACU/Da02S8MF7Co/s1600/cycle.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Iteration 0&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I will discuss the requirements for this project and start defining stories and their scenarios/conditions of acceptance.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9168000460138974508-7678406263475243121?l=airasoul.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://airasoul.blogspot.com/feeds/7678406263475243121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/7678406263475243121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9168000460138974508/posts/default/7678406263475243121'/><link rel='alternate' type='text/html' href='http://airasoul.blogspot.com/2011/02/behaviour-driven-development-with-mspec.html' title='Behaviour Driven Development with MSpec, SpecFlow, and Friends'/><author><name>Andrew Keig</name><uri>http://www.blogger.com/profile/05713005549773450601</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/-Cvx1xnUx35M/TvsGnOsZQLI/AAAAAAAAAGM/1C3ppHscqm0/s220/droid.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-1bQgES38LQU/TV5ZrQdW_ZI/AAAAAAAAACU/Da02S8MF7Co/s72-c/cycle.jpg' height='72' width='72'/><thr:total>1</thr:total></entry></feed>
