<?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-37105559</id><updated>2011-04-21T21:36:47.612-07:00</updated><category term='ruby'/><category term='launchy'/><category term='User Centered Design'/><category term='PATH'/><category term='continuous integration'/><category term='commandline'/><category term='ant'/><category term='java'/><category term='procexp'/><category term='cruisecontrol java monitor Big visible charts agile ramaze ruby'/><category term='process'/><category term='maven build tools'/><category term='github pages blog jekyll accordion.js accordion prototype1.6 javascript opensource'/><category term='UCD'/><category term='Junit'/><category term='save'/><category term='thoughtworks'/><category term='selenium'/><category term='java5'/><category term='jruby Mac OSX install Windows CLASSPATH'/><category term='sysinternals'/><category term='testing &quot;random numbers&quot; ruby'/><category term='batch files'/><category term='Agile'/><category term='junit4'/><category term='mocking'/><category term='rails'/><category term='errors'/><category term='cruisecontrol'/><category term='top'/><category term='webrick'/><category term='testing'/><category term='automation'/><category term='env'/><title type='text'>beta</title><subtitle type='html'>Version x.1 - drafting random thoughts</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-37105559.post-4155299905021004474</id><published>2009-01-20T09:16:00.001-08:00</published><updated>2009-01-20T09:16:12.698-08:00</updated><title type='text'>SQL by created on</title><content type='html'>Model.find(:all, :conditions =&gt; ["date(created_on) = date ( ? )", Date.today.to_s(:db) ])&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-4155299905021004474?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/4155299905021004474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=4155299905021004474' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/4155299905021004474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/4155299905021004474'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2009/01/sql-by-created-on.html' title='SQL by created on'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-6390582519581082375</id><published>2009-01-19T13:19:00.001-08:00</published><updated>2009-01-19T13:19:08.140-08:00</updated><title type='text'>Views and Boolean query methods</title><content type='html'>Code smell: a Boolean query method in your views like a has? Or is?&lt;br /&gt;Solution : move it to a helper or better yet the model&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-6390582519581082375?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/6390582519581082375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=6390582519581082375' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/6390582519581082375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/6390582519581082375'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2009/01/views-and-boolean-query-methods.html' title='Views and Boolean query methods'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-8446334318393733620</id><published>2009-01-16T21:15:00.000-08:00</published><updated>2009-01-16T21:18:45.581-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='github pages blog jekyll accordion.js accordion prototype1.6 javascript opensource'/><title type='text'>Using github pages</title><content type='html'>Started using github pages for this blog. Made a couple of posts.&lt;br /&gt;&lt;a href="http://betarelease.github.com/2009/01/11/moved_to_github_pages.html "&gt;&lt;br /&gt;Find out how easy it is to blog on github&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Also released accordion.js that is much simpler and completed tested. Check it out here.&lt;br /&gt;&lt;a href="http://betarelease.github.com/2009/01/16/accordion_in_javascript.html"&gt;accordion.js announcement&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-8446334318393733620?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/8446334318393733620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=8446334318393733620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/8446334318393733620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/8446334318393733620'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2009/01/using-github-pages.html' title='Using github pages'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-8218596895026561590</id><published>2009-01-04T10:04:00.000-08:00</published><updated>2009-01-04T10:05:39.015-08:00</updated><title type='text'>Encapsulation</title><content type='html'>The idea of block structure originated with the programming language Algol 60. It appears in most advanced programming languages and is an important tool for helping to organize the construction of large programs. - &lt;a href="http://www.amazon.com/Structure-Interpretation-Computer-Programs-Engineering/dp/0262011530"&gt;SICP&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;* Block Structuring is a way for a procedure to have internal definitions that are local to that procedure. This prevents name collision at minimal and provides simplification. Along with this it also allows the user to unclutter their minds and think in terms of details they are interested in. Splitting a program into smaller procedures and internalising a lot of details leads to good *encapsulation* and better understanding of the overall program. &lt;br /&gt;&lt;br /&gt;Inspite of it being such an old idea why do I still come across code that has 300 lines of if_else, case_switch statements in a single big method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-8218596895026561590?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/8218596895026561590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=8218596895026561590' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/8218596895026561590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/8218596895026561590'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2009/01/encapsulation.html' title='Encapsulation'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-7365610561391683529</id><published>2008-12-26T06:49:00.000-08:00</published><updated>2008-12-28T11:44:49.352-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cruisecontrol java monitor Big visible charts agile ramaze ruby'/><title type='text'>CruiseControl Monitor</title><content type='html'>Just put &lt;a href="http://github.com/betarelease/cc_monitor/tree/master"&gt;CruiseControl Monitor &lt;/a&gt;project on github. It is very 0.1 but all the current features work. Thanks to the team in Pune who showed me this wonderful but extremely skinny application that brings lot of visibility. Special thanks to Nigel Fernandes. Extra special thanks to Thomas Czarniecki from the Australia office who was so open to sharing his project and allowing me to be in the driver seat.&lt;br /&gt;&lt;br /&gt;This kind of a project already exists for CruiseControl.NET which can do much more than just CC Monitor. But there was nothing in the Java or Ruby.&lt;br /&gt;&lt;br /&gt;From the Readme file:&lt;br /&gt;&lt;br /&gt;DESCRIPTION--&lt;br /&gt;&lt;br /&gt;CC Monitor as the name suggests allows you to monitor multiple Continuous Integration environments. Currently it can parse cc_tray compatible xml for CruiseControl.&lt;br /&gt;CC Monitor collects all the build information and puts it on a dashboard. CC Monitor is different that the dashboard that comes with Cruisecontrol. With CC Monitor you can actually monitor different Cruisecontrol environments just by specifying the location of the cc_tray.xml file.&lt;br /&gt;&lt;br /&gt;CC Monitor provides a big visible display which can be projected to the whole development room. Having a big visible display of Cruise builds can help the team monitor the health of the code all the time and they do not need to look at their local CruiseControl Monitors.&lt;br /&gt;&lt;br /&gt;Currently it can display information that is part of the xml file. Apart from that it also displays the progress over a period of time to indicate how healthy the application has been.&lt;br /&gt;&lt;br /&gt;Features to come:&lt;br /&gt;&lt;br /&gt;1. Adding graphical display for health of application over time&lt;br /&gt;2. Resetting graphs daily&lt;br /&gt;3. Adding audible indications to the monitor&lt;br /&gt;4. Better graphics to indicate the status of the build&lt;br /&gt;5. Marking fix owners for broken builds&lt;br /&gt;and many more....&lt;br /&gt;&lt;br /&gt;USAGE--&lt;br /&gt;&lt;br /&gt;To use just download and change the project url in controller/main.rb.&lt;br /&gt;&lt;br /&gt;Type 'rake monitor:clean' - to setup the database&lt;br /&gt;then type&lt;br /&gt;'rake monitor:start'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PS: It uses amazing ramaze.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-7365610561391683529?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/7365610561391683529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=7365610561391683529' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/7365610561391683529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/7365610561391683529'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/12/cruisecontrol-monitor.html' title='CruiseControl Monitor'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-1759227613377711861</id><published>2008-10-07T20:29:00.001-07:00</published><updated>2008-10-07T20:29:56.769-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maven build tools'/><title type='text'>Quote for the day</title><content type='html'>Maven .... What is it good for?.. Absolutely nothing..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-1759227613377711861?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/1759227613377711861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=1759227613377711861' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/1759227613377711861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/1759227613377711861'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/10/quote-for-day.html' title='Quote for the day'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-5429610035179599110</id><published>2008-10-07T20:07:00.000-07:00</published><updated>2008-10-07T20:15:01.450-07:00</updated><title type='text'>MySQL and Unsigned integer in Rails</title><content type='html'>Rails does not allow you to create unsigned integer in an intuitive way.&lt;br /&gt;For example&lt;br /&gt;&lt;br /&gt;t.integer user_id, :unsigned =&gt; true&lt;br /&gt;&lt;br /&gt;will not work.&lt;br /&gt;&lt;br /&gt;To make it work you will have to do &lt;a href="http://dev.rubyonrails.org/ticket/5219"&gt;http://dev.rubyonrails.org/ticket/5219&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;t.column user_id, 'integer unsigned'&lt;br /&gt;&lt;br /&gt;or use &lt;a href="http://brentrubyrails.blogspot.com/2007/11/assigning-custom-data-types-to-new.html"&gt;http://brentrubyrails.blogspot.com/2007/11/assigning-custom-data-types-to-new.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;or use the &lt;a href="http://thewebfellas.com/blog/2008/6/2/unsigned-integers-for-mysql-on-rails/#comment-1924"&gt;patch&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;On Linux you may get a &lt;span style="font-style: italic; color: rgb(255, 0, 0);"&gt;/tmp/mysql.sock&lt;/span&gt; not found error to fix that locate mysql.sock(or mysqld.sock)&lt;br /&gt;which should typically be found in &lt;span style="color: rgb(255, 0, 0);"&gt;/var/run/mysqld/mysqld.sock&lt;/span&gt; or &lt;span style="color: rgb(255, 0, 0);"&gt;/var/local/lib/mysql.sock&lt;/span&gt; or some place around. (whereis '&lt;span style="color: rgb(255, 0, 0);"&gt;mysql.sock&lt;/span&gt;' should be of help here.).&lt;br /&gt;Make sure you add a '&lt;span style="color: rgb(255, 0, 0);"&gt;socket: /var/run/mysqld/mysqld.sock&lt;/span&gt;' entry in your database.yml for every instance of the database located on the&lt;br /&gt;local machine.&lt;br /&gt;&lt;br /&gt;On the network we are in we seem to get an 'EMULTIHOP' error accessing the local instance of mysql.&lt;br /&gt;The fix for that is to add a '&lt;span style="color: rgb(255, 0, 0);"&gt;host: 127.0.0.1&lt;/span&gt;'. I think this error appears only on networks that have something weird in their DNS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-5429610035179599110?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/5429610035179599110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=5429610035179599110' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/5429610035179599110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/5429610035179599110'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/10/mysql-and-unsigned-integer-in-rails.html' title='MySQL and Unsigned integer in Rails'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-9175114260931477688</id><published>2008-09-11T20:12:00.000-07:00</published><updated>2008-09-11T20:52:36.231-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='launchy'/><category scheme='http://www.blogger.com/atom/ns#' term='top'/><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='procexp'/><category scheme='http://www.blogger.com/atom/ns#' term='env'/><category scheme='http://www.blogger.com/atom/ns#' term='PATH'/><category scheme='http://www.blogger.com/atom/ns#' term='sysinternals'/><title type='text'>Launchy, Windows, Environment Variables etc.</title><content type='html'>I am working on a project that is JRuby, Javascript, Java, Maven, Ant, Rake and lots of css fun. But the even more fun part of it is that we are developing on Windows. It is really heartening to find how, Windows and application development on Windows is getting more and more annoying.&lt;br /&gt;&lt;br /&gt;To ease the pain I introduced a few tools on Windows.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx"&gt;ProcExp&lt;/a&gt; - www.sysinternals.com - is a very good task manager replacement. It is a free download and very light weight. It allows you to look at all processes(like doing a 'ps' or a 'top' on *nix) including system processes. You can kill a single process or a process tree. The benefit of looking at the tree is, you know how windows applications are spawning processes and how much memory/cpu they are eating up.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.launchy.net/"&gt;Launchy for windows&lt;/a&gt; - Inspired by QuickSilver on the MacOSX - this is a decent application launcher. It works similar to QuickSilver is finding and launching applications. Worth a look and download if you are still a fan of 'Quick launch toolbar' and now you have run out of task bar space to add more applications to be on single click. This way you will also use the keyboard more often and take your hand off the mouse.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Now the reason I am giving a special mention to both these applications is as follows :&lt;br /&gt;&lt;br /&gt;When you set Environment variables on Windows by navigating as follows 'My Computer -&gt;Right Click -&gt; Properties -&gt; Advanced -&gt; Environment Variables OR Control Panel -&gt; System -&gt; Advanced -&gt; Environment Variables(please let me know if you can do this without touching your mouse - that would be just brilliant) - we all know that you need to restart the Command Prompt for it to be able to load these new directories that you have added to the path. Except in this situation :&lt;br /&gt;&lt;br /&gt;When you have Launchy and if you launch command prompt through launchy. Restarting Command Prompt will not help in this case, because the command prompt that was launched by Launchy receives its context from Launchy. And if Launchy was started before you made the changes to the Environment Variables, Launchy will pass on this old context to Command Prompt. In this case you will have to restart Launchy so that the Environment Variables are updated and all the applications that are started by Launchy will have the updated Environment variables.&lt;br /&gt;I could trace this because of ProcExp - as it showed the tree of processes and their parent-child relationship.&lt;br /&gt;&lt;br /&gt;So if you have Launchy - restart Launchy after you change Environment Variables on Windows.&lt;br /&gt;&lt;br /&gt;Another thing that I was hurt by and my colleague &lt;a href="http://www.imdb.com/name/nm2732137/"&gt;Chris Kozak&lt;/a&gt;* rightly attributed to being a windows problem is - when you add a new Environment Variable - it is not available till you restart Windows. Whosoever said that a registry was a good idea and doing it Windows style is better must have been looking at the stars.....&lt;br /&gt;&lt;br /&gt;I am glad that I have a *nix system on my personal machine. Its just more logical.&lt;br /&gt;&lt;br /&gt;*No developer Chris Kozaks were harmed in the making of this post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-9175114260931477688?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/9175114260931477688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=9175114260931477688' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/9175114260931477688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/9175114260931477688'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/09/launchy-windows-environment-variables.html' title='Launchy, Windows, Environment Variables etc.'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-3365977935275413291</id><published>2008-08-13T19:36:00.000-07:00</published><updated>2008-08-21T21:59:52.153-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testing &quot;random numbers&quot; ruby'/><title type='text'>Testing randomness in your application</title><content type='html'>I was involved in writing an application which involved pairing participants up for activities. One thing we had to limit was that every participant was paired with 4 other participants. That way the burden would be even on all participants and the distribution of activities would be fair.&lt;br /&gt;&lt;br /&gt;Another aspect of this story was to make sure we could do this repeatedly and ensure that a participant is not paired with the same one in the next cycle.(We wanted to come up with a way to do this automatically every so often.)&lt;br /&gt;&lt;br /&gt;When we went ahead and analysed this story we found out that, pairing similar to this was being done manually where someone would pick names and assign them. Fairness was verified manually.&lt;br /&gt;&lt;br /&gt;This process of throwing pieces of paper and picking names worked for small groups and it became a nightmare once we wanted to do this multiple times. Often we would come across repeated pairs and confusion about what is fair and what is not. The randomness of the whole thing was arbitrary and error prone.&lt;br /&gt;&lt;br /&gt;Having known all that we starting designing this story. Figuring out the tests was our next task. We started writing tests but all we ended up with was something that said &lt;span style="color: rgb(255, 102, 102);"&gt;"test_random_numbers_are_generated"&lt;/span&gt; and the body of the test could only go about white box testing the fact that the randomization method was called. Writing different variations gave us something we already knew about. We also went about testing the math behind randomization - which we dropped after initial attempts - since it was clearly testing implementation.&lt;br /&gt;&lt;br /&gt;Intrigued with the idea of using random numbers  the inherent difficulty of testing random numbers &lt;a href="http://flexting.blogspot.com/"&gt;Paulo&lt;/a&gt;(who I was working with then) asked how could we test randomization - its almost untestable - he said.&lt;br /&gt;&lt;br /&gt;Stepping back and looking at the problem from a the business requirement  looking at the desired behavior we started rethinking about our tests and moving away from testing random numbers. What we found was the application as such never cared about randomization. All that the administration was interested in was with the fairness of the pairing. Another thing that was implicit in this requirement was that a person cannot be paired with self. Randomness was our implementation detail and it was how we were thinking about implementing this. Also we did not even need the random numbers provided by ruby. All we needed was&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;def test_association_with_parity&lt;br /&gt;parity = 2&lt;br /&gt;set = [1,2,3,4,5,6,7,8,9,10]&lt;br /&gt;relations = Relation.associate_with_parity(set, parity)&lt;br /&gt;relations.each do |index, value|&lt;br /&gt; assert_equal parity, value.size&lt;br /&gt; assert_equal false, value.include?(index)&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;def test_should_ensure_parity_with_no_duplicates&lt;br /&gt;User.randomize &lt;br /&gt;has_no_duplicates(some_user.pairs)&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In both these tests the acceptance criteria do not care about randomness of the result. Also it does not matter how this randomness if at all is implemented. What matters is the fairness of the pairing and that there is no one who pairs with self.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 102, 102);"&gt;In summary I would say that if you are thinking about testing randomness - your application may need another look.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Try asking the question - Does my domain care about the randomness(implementation)? - More often than not your answer would be NO and you will be able to figure out better functional tests for your application. Once you start thinking in terms of behavior of the system instead of the implementation, you will end up with better tests.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-3365977935275413291?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/3365977935275413291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=3365977935275413291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/3365977935275413291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/3365977935275413291'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/08/testing-randomness-in-your-application.html' title='Testing randomness in your application'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-4949906566511706087</id><published>2008-07-29T07:35:00.000-07:00</published><updated>2008-07-29T07:44:33.777-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Junit'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='java5'/><category scheme='http://www.blogger.com/atom/ns#' term='commandline'/><category scheme='http://www.blogger.com/atom/ns#' term='ant'/><category scheme='http://www.blogger.com/atom/ns#' term='junit4'/><title type='text'>Java 5.0 and Junit 4</title><content type='html'>While working on some Java code and working with Java 5.0 and Junit4.4 I started by writing some examples and tests.&lt;br /&gt;&lt;br /&gt;I would say it was a very pleasant experience working on the new JUnit with Java 5. Parts of code became a lot clearer and easy to read. Lot of clutter was hidden behind more aptly named annotations(For the critics of everything annotated - "Right now we are just talking about good things").&lt;br /&gt;&lt;br /&gt;I ran across a lot of issues when using Junit4(most of it was my ignorance.) Some of the following links helped me understand how Junit4 was different.&lt;br /&gt;&lt;a href="http://junit.sourceforge.net/doc/faq/faq.htm#tests_13"&gt;Junit FAQ&lt;/a&gt;&lt;br /&gt;&lt;a href="http://nose.xephyrus.com/Arkle-junit4_basics"&gt;Junit 4 Basics&lt;/a&gt;&lt;a href="http://today.java.net/pub/a/today/2006/12/07/junit-reloaded.html"&gt;&lt;br /&gt;What's new in Junit 4.4&lt;/a&gt;&lt;br /&gt;&lt;a href="http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&amp;amp;f=33&amp;amp;t=020166"&gt;NoClassDefFoundError with Junit 4.4&lt;/a&gt; (This was the first error I had to deal with when running tests using the command line or ant)&lt;br /&gt;&lt;a href="http://cleveralias.blogs.com/thought_spearmints/2005/11/index.html%20%28"&gt;Converting tests from Junit 3.8 to JUnit 4.4&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When using Junit4 on command line the following JUnit3 command&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;java -classpath lib\junit.jar;build\prod\com\MyProject\;build\test\com\MyProject junit.textui.TestRunner com.MyProject.MyTest&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;becomes&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;java -classpath lib/junit-4.4.jar;build org.junit.runner.JUnitCore com.MyProject.MyTest&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note the change of runner class in Junit4. Happy Testing with Junit4.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-4949906566511706087?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/4949906566511706087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=4949906566511706087' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/4949906566511706087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/4949906566511706087'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/07/java-50-and-junit-4.html' title='Java 5.0 and Junit 4'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-9081068940589438876</id><published>2008-06-20T23:08:00.000-07:00</published><updated>2008-08-23T13:40:07.964-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jruby Mac OSX install Windows CLASSPATH'/><title type='text'>Installing jRuby on Mac OS X</title><content type='html'>I was trying to install and run jruby on my mac(Jruby 1.1.2). After downloading and unzipping the installer I tried to run jruby.&lt;br /&gt;But all I was getting was an exception&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Exception in thread "main" java.lang.NoClassDefFoundError: org/jruby/Main&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Googling did not yield anything useful.&lt;br /&gt;So I started debugging and I found that the CLASSPATH had not been specified correctly in the&lt;br /&gt;jruby file.&lt;br /&gt;All I was getting was an empty string for the CLASSPATH which is why it was not able to find the jruby.jar(which contains the org.jruby.Main class)&lt;br /&gt;&lt;br /&gt;To fix this I added&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 102, 102);"&gt;CLASSPATH=./../lib/jruby.jar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;before CLASSPATH was being used in the jruby file.&lt;br /&gt;&lt;br /&gt;Looks like CLASSPATH has not been defined in the jruby.bat file too. So jruby won't work on Windows either.&lt;br /&gt;&lt;br /&gt;Hope this tip helps someone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-9081068940589438876?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/9081068940589438876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=9081068940589438876' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/9081068940589438876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/9081068940589438876'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/06/installing-jruby-on-mac-os-x.html' title='Installing jRuby on Mac OS X'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-6300377198297577549</id><published>2008-03-13T22:55:00.000-07:00</published><updated>2008-03-13T23:04:14.979-07:00</updated><title type='text'>Somethings I did not expect from a Mac</title><content type='html'>I got a Mac (the new and shiny Mac Book Pro with 2.4Ghz processor and 2GB RAM and 120GB harddisk). I was very&lt;br /&gt;excited and feeling very cool about my new possesion(thanks to a couple of secret angels in the world).&lt;br /&gt;I was becoming excited about doing things differently(or doing them more intuitively as it were), with my Mac.&lt;br /&gt;And so I did - it started when I began experiencing the sleekness of the product.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Its weight way under the bulkiness of my old Dell Latitude D620.&lt;/li&gt;&lt;li&gt;The keyboard has just the number of keys you normally use - also the multi-function function keys (especially the F9-F12 set.)&lt;/li&gt;&lt;li&gt;The comfort of using one click trackpad and the clever use of programmability to add on the right click functionality of the track pad. - I am more of a mouse user though.&lt;/li&gt;&lt;li&gt;The presence of the apple key(ohhh it so much looks and sometimes works like the Windows key on my Dell- but more about that in a bit.)&lt;/li&gt;&lt;li&gt;MacOSX packed with the power of Unix under the hood - thats just brilliant - Now anything I want to setup is just a hack/script away. - Best thing to happen to Operating Systems since Windows(just kidding...)&lt;/li&gt;&lt;li&gt;Placement of speakers as well as the camera is just right.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Some pain points on my Mac (or how Mac missed the bus on some of the key aspects of usability for a developer)&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Leopard when launched in December had this bug - the keyboard freezes occasionally. For about 2 months the only solutions were - wait till Mac unfreezes the keyboard on its own or try restarting it(Windows contributed this elixir to software - if it does not work reboot) Thankfully the newest firmware release is supposed to take care of that(fingers crossed). (Another fix I heard was to press on the area between the space bar and the track pad with your thumb for a bit - let me know if it works) - latest update is that on some machines the keyboard firmware update did not fix this. So cross your fingers.&lt;/li&gt;&lt;li&gt;Finder does not show you the hidden files - thanks to all the programmers out there who wrote TinkerTool which helps you do just that. (whereas on windows there is a setting for this - how thoughtful of you Bill)&lt;/li&gt;&lt;li&gt;The applications on Mac are under the Applications folder as Applications/appname.app/Contents/MacOS/app...(isnt this a mac.. having a macOS directory under each one of these is just redundant - especially when you install this application through the dmg installer.)&lt;/li&gt;&lt;li&gt;The Menu items are not mapped to keys - Alt+F+O does not open a new file or Alt+F does not take me to the File menu ...&lt;/li&gt;&lt;li&gt;An important annoyance that comes to mind when using a Mac - they mapped the apple key to do what Control key does on any other OS - Windows, linux, Solaris -&lt;br /&gt;all respond to Ctrl+C and Ctrl+V for copying and pasting. Why would Mac want to be different? Why are they not following the convention?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;My Iphone&lt;/span&gt;&lt;br /&gt;My iPhone was something that I bought just after I got the Mac and I am very proud to say that I have an unlocked iphone with the latest firmware(1.1.3 - I know the unlocking software works with 1.1.4 but I haven't had the time to update) thanks to Zibri(http://www.hackthatifone.com/forum/index.php?topic=42.0), thanks to GeoHotz(http://iphonejtag.blogspot.com/) and thanks to all those who strived days and nights to get all the iphones to unlock and make numerous iphone owners proud.&lt;br /&gt;&lt;br /&gt;I am very happy with the unlocked iphone especially with the OSX under the hood.&lt;br /&gt;All the software that I can install on it(when I last checked I could put VNC and ssh on it.. ) - hackers prevail.&lt;br /&gt;The usability is splendid (thanks Steve Jobs) - except the well known annoyances (viz. cannot forward messages, cannot send messages to a list, no zoom/video on camera) - apparently&lt;br /&gt;there are softwares available which can fix all of these in some way.&lt;br /&gt;The biggest problem is with the Camera part - where I need to use iPhoto to download pictures.&lt;br /&gt;I have found out since then that on Windows the iPhone shows up as a disk and pictures and songs can be transferred&lt;br /&gt;like on a USB key. - But on a Mac I cannot do it. The iphone is not mounted as a volume either.How annoying???????&lt;br /&gt;&lt;br /&gt;I am sure even with all this I will still prefer my Mac. But the Mac by no means is the best in usability. I am going to collect all these annoyances(maybe there can be a annoyanceswithMac.com to compete with annoyances.org ) and keep an updated list.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-6300377198297577549?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/6300377198297577549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=6300377198297577549' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/6300377198297577549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/6300377198297577549'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/03/somethings-i-did-not-expect-from-mac.html' title='Somethings I did not expect from a Mac'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-2321204499216272045</id><published>2008-01-04T14:24:00.000-08:00</published><updated>2008-01-15T01:58:07.321-08:00</updated><title type='text'>Using Verizon EVDO card on Windows and Linux</title><content type='html'>I am using the Verizon Wireless EVDO card on my Dell D620 and it has been a life saver a number of times. It connects and keeps the connection without any hiccups. What I did not like was the bundled software that came with it(which required me to enter so much information about the card and configure it to be used). The bundled software also adds features(that u don't like) like monitoring and controlling all of your wireless networks - thus taking over control of the other wireless options on my machine - 802.11g and bluetooth.&lt;br /&gt;It also adds a useless(irritating) feature of compressing data transfer with Venturi.&lt;br /&gt;&lt;br /&gt;I was trying to use the card on my linux partition and found out that all that the EVDO card does is adds itself as a modem for dialup using PPP. I found quick and easy instructions for using &lt;a href="http://www.linux.com/articles/52729"&gt;EVDO on Ubuntu Linux&lt;/a&gt;. I can do all this on linux through a shell command.&lt;br /&gt;For getting the same smooth usability there is a little more work required on windows.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Windows does detect the card as a Modem(Curitel PC Card) and can be easily configured&lt;br /&gt;to use PPP dialing.&lt;br /&gt;&lt;br /&gt;Here is how you do it.&lt;br /&gt;&lt;br /&gt;From Network Configuration&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Select "Create a new connection"&lt;/li&gt;&lt;li&gt;Choose "Connect to the Internet"&lt;/li&gt;&lt;li&gt;Choose "Setup my connection manually"&lt;/li&gt;&lt;li&gt;Choose "Connect using a dial-up modem"&lt;/li&gt;&lt;li&gt;Choose "Modem - Curitel PC Card(COM4)"&lt;/li&gt;&lt;li&gt;"Enter an ISP name" (this is your name for the connection and has nothing to do with the ISP)&lt;/li&gt;&lt;li&gt;Phone number to enter would be "#777"&lt;/li&gt;&lt;li&gt;Uncheck "Use this account name and password when anyone connects to  the internet from this computer"&lt;/li&gt;&lt;li&gt;Uncheck "Make this the default connection"&lt;/li&gt;&lt;li&gt;Click "Finish"&lt;/li&gt;&lt;/ul&gt;The newly created connection starts dialing immediately and will&lt;br /&gt;will open a prompt to enter Username and Password -&lt;br /&gt;&lt;br /&gt;Click "Properties" on the prompt&lt;br /&gt;&lt;br /&gt;Verify  that&lt;br /&gt;In the "General" tab&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"Modem - Curitel PC Card(COM4)" is checked&lt;/li&gt;&lt;li&gt;Phone number shows as "#777"&lt;/li&gt;&lt;li&gt;Check "Show icon in notification area when connected"&lt;/li&gt;&lt;li&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;In "Options" tab&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Check "Display progress while connecting"&lt;/li&gt;&lt;li&gt;Uncheck "Prompt for username, password, certificate, etc."&lt;/li&gt;&lt;li&gt;Uncheck "Prompt for phone number"&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_99A2NrVKgk8/R362q2nNsWI/AAAAAAAAA5M/0ho6w1iuDCw/s1600-h/connect+using.PNG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_99A2NrVKgk8/R362q2nNsWI/AAAAAAAAA5M/0ho6w1iuDCw/s320/connect+using.PNG" alt="" id="BLOGGER_PHOTO_ID_5151755871089176930" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In Networking ensure&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"Type of dialup server I am calling" is set to "PPP: Windows 95/98/NT, Internet"&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"This connection uses following items" shows Internet Protocol (TCP/IP) as checked, QoS Packet Scheduler as checked, Deterministic network enhancer as checked&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_99A2NrVKgk8/R3627WnNsXI/AAAAAAAAA5U/bs6mkGLVEKE/s1600-h/networking.PNG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_99A2NrVKgk8/R3627WnNsXI/AAAAAAAAA5U/bs6mkGLVEKE/s320/networking.PNG" alt="" id="BLOGGER_PHOTO_ID_5151756154557018482" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now from you Network Configuration double click to connect using these connection settings.&lt;br /&gt;You can create a shortcut and save it on the desktop for faster access.(Standard Windows operating procedure)&lt;br /&gt;&lt;br /&gt;You should see the balloon in the notification area(system tray) indicating that you are connected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-2321204499216272045?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/2321204499216272045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=2321204499216272045' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/2321204499216272045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/2321204499216272045'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2008/01/using-verizon-evdo-card-on-windows-and.html' title='Using Verizon EVDO card on Windows and Linux'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_99A2NrVKgk8/R362q2nNsWI/AAAAAAAAA5M/0ho6w1iuDCw/s72-c/connect+using.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-5402663168616993995</id><published>2007-09-01T20:35:00.000-07:00</published><updated>2007-09-07T21:09:04.381-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='save'/><category scheme='http://www.blogger.com/atom/ns#' term='mocking'/><title type='text'>rails - save! broke the contract - mocking to rescue</title><content type='html'>Detail descriptions of &lt;a href="http://www.martinfowler.com/articles/mocksArentStubs.html"&gt;mockist and classicist&lt;/a&gt; are on Martin Fowler's blog.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Consider&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;class Person &amp;lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    #has name, address, home, business, cell phone numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.... more object behaviour&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The intended behaviour is to do some system specific tasks incognito - lets say send an email to all his friends.&lt;br /&gt;&lt;br /&gt;So we alias the save method as follows&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;alias :save_with_notification, :save&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def save_with_notifications&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;send_emails&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;save&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&lt;br /&gt;This works well for save. But when somewhere we call save! it all breaks - i.e. our save_with_notifications is not called and nobody gets notified.&lt;br /&gt;&lt;br /&gt;The root cause(as analysed by David Vollbracht (not &lt;a href="http://davidvollbracht.com/"&gt;this&lt;/a&gt; one)) of this problem was this piece of rails code&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def save&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create_or_update&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;# Attempts to save the record, but instead of just returning&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;# false if it couldn't happen, it raises a&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;# RecordNotSaved exception&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def save!&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create_or_update || raise(RecordNotSaved)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;save! does not call save.&lt;br /&gt;&lt;br /&gt;On further investigation I found functional tests around the base class for active_record.&lt;br /&gt;&lt;br /&gt;But what was missed was a good unit test with mocking like so&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;test "save! should successfully save object by calling save" do&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;base = Base.new&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;base.expects(:save).returns(true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assert_nothing_raised base.save!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;test "save! should throw on exception if save fails" do&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;base = Base.new&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;base.expects(:save).returns(false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assert_raises RecordNotSaved, base.save!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&lt;br /&gt;Here is a place where mocking does a much better job at testing a specific contract that is a convention and was missed due to black box testing.&lt;br /&gt;&lt;br /&gt;This is not the only way to fix this problem though.&lt;br /&gt;&lt;br /&gt;The real problem is that the requirements did not capture the fact of aliasing save or save! methods.&lt;br /&gt;&lt;br /&gt;Testing this scenario functionally is perfectly possible though the testing could get more involving.&lt;br /&gt;&lt;br /&gt;The tests in that case would make sure that aliasing of save method does not break save!.&lt;br /&gt;&lt;br /&gt;But the above mocked tests are as simple as it gets and they reflect the simpler(obvious?) underlying requirement of save! calling save.&lt;br /&gt;&lt;br /&gt;&lt;span font-size="small"&gt;Note: Formatting code on blogger sucks&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-5402663168616993995?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/5402663168616993995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=5402663168616993995' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/5402663168616993995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/5402663168616993995'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2007/09/mocking-is-really-useful-one-instance.html' title='rails - save! broke the contract - mocking to rescue'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-2982609902781303974</id><published>2007-05-09T06:14:00.001-07:00</published><updated>2007-05-09T06:14:01.631-07:00</updated><title type='text'>:partials are objects - too..</title><content type='html'>&lt;p&gt;My recent adventures with ruby and rails have been on an actual application that will be used by 1000s of users. This application seems to suit perfectly for the design of rails. The good thing is that there are not many database transactions, mostly the users are expected to read and search for stuff on this website.&lt;br /&gt;&lt;br /&gt;Many parts of this application are reusable. What changes most of the times is the way the parts look like when they are appear in different parts of the website. Also some times the details of those parts behave in different ways on different views(ajax/non-ajax, popup/tab-module, associated/unassociated, etc.).&lt;br /&gt;&lt;br /&gt;This behaviour actually make them perfect candidates to be partials so that they can be programmed once and then the view can overlay and change what and how it shows up.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;There are some things that really impress me about ruby - especially the part where everything is an object and the duck typing. Also having started doing real object oriented programming since I joined ThoughtWorks ( the other way of doing &amp;quot;OOP&amp;quot; is where I have a Universe class which knows about everything - that was so easy to do in those days), my mindset of trying to find objects has changed the way I write software.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;With ruby - when used correctly - all these concepts fit perfectly. Ruby by design allows you excellent encapsulation - a very important feature of OO Design( eg. the duck typing - u only need to know whether it quacks like a duck - no internals are exposed when responding to a message). Rails tries to take these constructs in ruby one level further to the web application level, where the views also can be treated as objects(another important layer that can be treated like an object is the database layer using ActiveRecord).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;What I like about the views in rails is that the views can be directly rendered from the actions(no clumsy xml mapping required). Also, the flexibility of using partials in my rhtml code.&lt;br /&gt;&lt;br /&gt;A little bit about &lt;strong&gt;:partials&lt;/strong&gt; - &lt;strong&gt;partials&lt;/strong&gt; are something similar to 'include' tags in html where one can create parts of a webpage and bring them together using 'include file'. Creating multiple html files helps reuse of contents on a website - so that one can show a consistent header menu for example all through the website - and also keeps the html code DRY.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;:partial&lt;/strong&gt; builds on this idea. In rails one can create an rhtml file(which is actually interpretable ruby) that rails automagically handles for you to create html content. What can further be done is separate code that one wants to reuse in a file that starts with an underscore eg. _photos.rhtml.&lt;br /&gt;&lt;br /&gt;There are multiple benefits of this breaking of code &lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;    &lt;li&gt;code is now more readable - when u see a partial that you are not concerned about u can just ignore it and focus on the task u are doing(say u have _photos and _videos partials and you are currently working on the videos part - you dont have to worry about what the _photos partial is doing)&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;code is much more unit testable - rspec is excellent at testing :partials (My colleagues &lt;a href="http://m2ward.blogspot.com/"&gt;Mike&lt;/a&gt; and &lt;a href="http://jakescruggs.blogspot.com/2007/04/stubbingmocking-partial-within-partial.html"&gt;Jake&lt;/a&gt; can help you with that)&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;code is much more testable as a whole - mocking out partials at a time can greatly simplify testing - again rspec is your friend.&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;code is DRY&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;In your 'my multimedia page' (multimedia.rhtml) can look like&lt;br /&gt;&lt;span style="font-family:Courier"&gt;&amp;lt;% @some_variables %&amp;gt;&lt;br /&gt;&amp;lt;% some_other_variables %&amp;gt;&lt;br /&gt;render :partial =&amp;gt; 'path/to/photos/photos.rhtml'&lt;br /&gt;&amp;lt;% some_more_ruby_code %&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;when _photo.rhtml looks like&lt;br /&gt;&lt;span style="font-family:Courier"&gt;&amp;lt;% @some_variable1 manipulation %&amp;gt;&lt;small&gt;Tags: &lt;a rel="tag" href="http://technorati.com/tag/partial"&gt;partial&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/ruby"&gt;ruby&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/rails"&gt;rails&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/encapsulation"&gt;encapsulation&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/refactoring"&gt;refactoring&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/rspec"&gt;rspec&lt;/a&gt;&lt;/small&gt;&lt;br /&gt;&amp;lt;% @some_variable2 manipulation %&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The beauty here is the simplicity with which the _photos.rhtml can be separated. What rails does more is that the '@some_variables' that showed up in  multimedia.rhtml is automatically available to the :partial. Isn't that awesome one would say - and it is for a start.&lt;br /&gt;But when there are many of these rhtml file that render more of these partials and all the variables are now the @variables one can get lost. Not only that the application is now getting too open - Let me explain.&lt;br /&gt;With a tree of these partials multimedia -&amp;gt; photos -&amp;gt; photo -&amp;gt; photo_detail,  if we follow the above pattern, the @variables from multimedia would now be available in photo_detail and this is when everything starts falling apart. Now when you refactor photo_detail you have to worry about how the @variables.&lt;br /&gt;This becomes more painful if you want to split the photo_detail and use the split portions together and separately at the same time. Then the problem of every &lt;strong&gt;:partial&lt;/strong&gt; knowing too much about every other &lt;strong&gt;:partial&lt;/strong&gt; - soon becoming a hairball so big that even cats will choke on them.&lt;br /&gt;To prevent this from happening one should think about &lt;strong&gt;:partials&lt;/strong&gt; as objects - this also goes well with the ruby philosophy of everything being an object.&lt;br /&gt;So when I say &lt;strong&gt;:partials&lt;/strong&gt; = objects all the laws of encapsulation apply.&lt;br /&gt;Having said that the multimedia.rhtml now looks like so&lt;br /&gt;&lt;span style="font-family:Courier"&gt;&amp;lt;% @some_variables %&amp;gt;&lt;br /&gt;&amp;lt;% some_other_variables %&amp;gt;&lt;br /&gt;render :partial =&amp;gt; 'path/to/photos/photos.rhtml', :locals =&amp;gt; {:photo_variable =&amp;gt; @some_variable1, :photo_caption =&amp;gt; @some_variable2, :photo_credit =&amp;gt; some_other_variable1 }&lt;br /&gt;&amp;lt;% some_more_ruby_code %&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Notice that now the &lt;strong&gt;:partial&lt;/strong&gt; can only care about the local variables that are passed to them it can be simplified to look like&lt;br /&gt;&lt;span style="font-family:Courier"&gt;&amp;lt;% photo_variable manipulation %&amp;gt;&lt;br /&gt;&amp;lt;% photo_caption manipulation %&amp;gt;&lt;br /&gt;&amp;lt;% photo_credit manipulation %&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Notice how all the @ signs disappeared in the &lt;strong&gt;:partial&lt;/strong&gt;. Also note how I could pass in a local variable from the rhtml to the &lt;strong&gt;:partial&lt;/strong&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This resolves a few issues :&lt;br /&gt;- Unit testing becomes a breeze - Since the &lt;strong&gt;:partial&lt;/strong&gt; is encapsulated testing the :partial in isolation is easy.&lt;br /&gt;- Reusing the&lt;strong&gt; :partial&lt;/strong&gt; becomes easy  - No more grand_parent to grand_son global variables&lt;br /&gt;- refactoring within the &lt;strong&gt;:partial&lt;/strong&gt; - not a problem - because you can write tests for this new functionality and refactor to create new partials - total insulation from the rest of the code.&lt;br /&gt;- refactoring the caller of the &lt;strong&gt;:partial&lt;/strong&gt; - even better since now you do not have to be afraid of breaking something because you removed an @variable.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This technique did help us refactor and increase our testing levels drastically.&lt;br /&gt;Hope it helps you too.&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-2982609902781303974?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/2982609902781303974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=2982609902781303974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/2982609902781303974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/2982609902781303974'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2007/05/partials-are-objects-too.html' title=':partials are objects - too..'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-6844621537570520050</id><published>2007-04-10T18:54:00.001-07:00</published><updated>2007-04-10T18:54:54.263-07:00</updated><title type='text'>Firefox, MySQL, Rails quirks</title><content type='html'>&lt;p&gt;&lt;span style="font-size:16pt"&gt;&lt;strong&gt;Firefox&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Firefox 2.0 has a new feature. It can remember sessions and reopen/reconnect to the same urls if Firefox was closed abruptly.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This helps a lot when you have to restart your Windows machine every so often. This feature becomes annoying especially when you want to automatically open Firefox, run Selenium tests and then close it. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Since this closing of the browser is considered abrupt(even though the tests are done the browser process is killed when we automate with Selenium) and the next time you open firefox - a popup appears asking you whether you want to 'Restore Session'. For the automation programs it is almost impossible to detect this pop-up and interact with it. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Firefox allows you to disable this feature and much more. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The trick is to type&lt;span style="font-family:Courier"&gt; 'about:config'&lt;/span&gt; in your Firefox address box. It shows you all the parameters you can set(including the ones for your plugins/addons). &lt;/p&gt;&lt;br /&gt;&lt;p&gt;There is a cool filter which lets you narrow down your search for a parameter and change it. The one I am referring to for 'Restore Session' is &lt;span style="font-family:Courier"&gt;'browser.sessionstore.enabled'&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:16pt"&gt;&lt;strong&gt;Rails 1.2 and '.' separators&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Starting Rails1.2 routes.rb makes as reserved and you cannot use a &lt;strong&gt;'.'&lt;/strong&gt; in your routes.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Enter :requirements - The workaround to using&lt;strong&gt; '.'&lt;/strong&gt; in your route elements.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For example: &lt;/p&gt;&lt;br /&gt;&lt;pre&gt;map.connect '/:controller/:action/:id', :controller =&amp;gt; 'wiki_pages', &lt;br /&gt;                                            :action =&amp;gt; 'show',&lt;br /&gt;                                            :requirements =&amp;gt; {:id =&amp;gt; /.*/}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This allows :id to contain&lt;strong&gt; '.'&lt;/strong&gt;s. A nice thing to note is that it supports any regexp.(ref :&lt;a href="http://forum.textdrive.com/viewtopic.php?pid=116742"&gt; http://forum.textdrive.com/viewtopic.php?pid=116742&lt;/a&gt;)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:16pt"&gt;&lt;strong&gt;MySQL and Windows&lt;/strong&gt;&lt;/span&gt; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;MySQL goes away(ref :&lt;a href="http://dev.mysql.com/doc/refman/5.0/en/gone-away.html"&gt; http://dev.mysql.com/doc/refman/5.0/en/gone-away.html&lt;/a&gt;) literally a number of times during the day on Windows. The solutions mentioned in this document&lt;/p&gt;&lt;br /&gt;&lt;p&gt;seem reasonable and logical but do not necessarily work. What worked this time is a machine restart. I also tried tweaking and setting all timeout values to a very large number but the problem does not completely go away.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Roderick wrote this&lt;a href="http://www.vandomburg.net/pages/mysql-ruby-windows"&gt; MySQL-Ruby-Windows&lt;/a&gt; thing. Worth a try if it can fix the windows timeout issue.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt; &lt;small&gt;Tags: &lt;a rel="tag" href="http://technorati.com/tag/firefox"&gt;firefox&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/rails"&gt;rails&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/mysql"&gt;mysql&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/windows"&gt;windows&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/dot+separator"&gt;dot separator&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/dot"&gt;dot&lt;/a&gt;, selenium&lt;/small&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-6844621537570520050?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/6844621537570520050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=6844621537570520050' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/6844621537570520050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/6844621537570520050'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2007/04/firefox-mysql-rails-quirks.html' title='Firefox, MySQL, Rails quirks'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-6263607434701460231</id><published>2007-03-27T21:34:00.001-07:00</published><updated>2007-09-20T21:02:45.638-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='cruisecontrol'/><category scheme='http://www.blogger.com/atom/ns#' term='automation'/><category scheme='http://www.blogger.com/atom/ns#' term='thoughtworks'/><category scheme='http://www.blogger.com/atom/ns#' term='webrick'/><category scheme='http://www.blogger.com/atom/ns#' term='selenium'/><title type='text'>Automated Testing and Continuous Integration with Selenium - How to do it out of the box...</title><content type='html'>&lt;p&gt;After struggliing with running Selenium with Cruisecontrol I hit on a new solution today and am now able to run Selenium and post results more consistently than before. This way of doing it has the advantages that I did not need to run a rails app to collect results. I have managed to do it with Webrick. Since it was my first time working with Webrick it took me lot longer than I thought. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;To start with, here is the problem I was facing. I was trying to do the Cruisecontrol with Selenium all over again on a fresh setup. Once I installed Cruisecontrol and Java(u have to have Java - I had ruby already). I was ready to run the same batch file I had. But I was not able to post the results. Installing a rails application with all the required gems seemed painful and an overkill for the purpose. So I started poking around with WEBrick. Some documentation on &lt;a href="http://www.webrick.org"&gt;WEBrick&lt;/a&gt; website got me started and I could send a request to the server. But what I was not able to do was read the request parameters. All the documentation I looked up talked about the same kinds of examples as on the WEBrick website. They all mentioned and showed with an example how to handle simple requests and responses. Printing out the request did not help as it did not have parameters anywhere. On further digging I found some code in the PickAxe book (edition 2 page 248)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;where the example spelled out exactly where the query object was 'req.query'. That was where one will find the parameters hash that Selenium populates when it posts results.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Here is a reference of the code that achieved the desired result.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'webrick'&lt;br /&gt;&lt;br /&gt;if ARGV.empty?&lt;br /&gt;  p &amp;quot;Usage: ruby post_results.rb browser_name&amp;quot;&lt;br /&gt;  p &amp;quot;Example: ruby post_results.rb iexplore&amp;quot; &lt;br /&gt;  exit(0)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;@browser = ARGV[0]&lt;br /&gt;url = APPLICATION_UNDER_TEST #&amp;quot;http://www.yourapp.com&amp;quot;&lt;br /&gt;testSuite=PATH_OF_TESTSUITE_RELATIVE_TO_SELENIUM&lt;br /&gt;resultsURL= &amp;quot;http://localhost:2000/postResults&amp;quot; #the server that gathers the results..&lt;br /&gt;testRunner=&amp;quot;#{url}/selenium/core/TestRunner.html?test=#{testSuite}&amp;amp;auto=true&amp;amp;resultsUrl=#{resultsURL}&amp;quot;&lt;br /&gt;command = &amp;quot;#{@browser} \&amp;quot;#{testRunner}\&amp;quot;&amp;quot;&lt;br /&gt;&lt;br /&gt;system &amp;quot;start #{command}&amp;quot; #DOS batch command start starts the command in a new thread&lt;br /&gt;&lt;br /&gt;include WEBrick&lt;br /&gt;&lt;br /&gt;s = HTTPServer.new( :Port =&amp;gt; 2000 )&lt;br /&gt;&lt;br /&gt;# HTTPServer#mount_proc(path){req, res ...}&lt;br /&gt;# You can mount also a block by `mount_proc'.&lt;br /&gt;# This block is called when GET or POST.&lt;br /&gt;def save_to_file(params)&lt;br /&gt;Dir.mkdir(&amp;quot;results&amp;quot;) unless FileTest.exist?(&amp;quot;results&amp;quot;)&lt;br /&gt;Dir.chdir(&amp;quot;results&amp;quot;)&lt;br /&gt;Dir.mkdir(@browser) unless FileTest.exist?(@browser)&lt;br /&gt;Dir.chdir(@browser)&lt;br /&gt;results_file_name = &amp;quot;selenium-results.html&amp;quot;&lt;br /&gt;&lt;br /&gt;save to file as before&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;s.mount_proc(&amp;quot;/postResults&amp;quot;){&amp;#124;req, res&amp;#124;&lt;br /&gt;  params = req.query&lt;br /&gt;  results_file_name = save_to_file(params)&lt;br /&gt;  s.shutdown&lt;br /&gt;  system &amp;quot;TASKKILL /F /IM #{@browser}.exe&amp;quot; #KILL the browser since selenium is done.&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;trap(&amp;quot;INT&amp;quot;){ s.shutdown }&lt;br /&gt;s.start&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-6263607434701460231?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/6263607434701460231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=6263607434701460231' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/6263607434701460231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/6263607434701460231'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2007/03/automated-testing-and-continuous_27.html' title='Automated Testing and Continuous Integration with Selenium - How to do it out of the box...'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-3357270080279177219</id><published>2007-03-02T20:53:00.001-08:00</published><updated>2007-03-04T16:52:18.164-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='automation'/><category scheme='http://www.blogger.com/atom/ns#' term='selenium'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><category scheme='http://www.blogger.com/atom/ns#' term='batch files'/><title type='text'>Automated Testing and Continuous Integration with Selenium</title><content type='html'>&lt;p&gt;&lt;span style="font-family:Arial;font-size:85%;color:#3333ff;"&gt;&lt;em&gt;For those who are closely following - this post has been edited for clarity of content and language ;) - ohh and to fit your screen&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&lt;a href="http://www.openqa.com/selenium"&gt;Selenium&lt;/a&gt; is a nice and slim tool for testing. If I may start with the history it was built by &lt;a href="http://www.jrandolph.com/blog/"&gt;Jason Huggins &lt;/a&gt;and Paul Gross* from ThoughtWorks and then opensourced on &lt;a href="http://www.openqa.com/selenium"&gt;http://www.openqa.com/selenium&lt;/a&gt; (List of all the contributors can be found there too).There are 2 versions of Selenium - Selenium Remote Control and Selenium core. Selenium core is the essence of Selenium where as Selenium RC packages the core to enable you to write tests in the language of your choice. There is a recorder (and much more) with Firefox which allows you to point and click and create your tests in any of the languages that Selenium RC supports.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;All these niceties made Selenium the choice of testing tool at my current project. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;Since it was designed by developers we also thought that Selenium was easy to automate. But as it turned out not so much. Here is the issues we faced and what we did to fix it. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;We tried to run Selenium in IE just to realise that we have a &lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy"&gt;same origin policy&lt;/a&gt; problem - we had our tests open http://localhost/ &lt;/span&gt;&lt;span style="font-family:Arial;"&gt;and then navigate to http://location.localhost/. &lt;strong&gt;Yes&lt;/strong&gt; you guessed it our domain name changed during the test run. This is what Selenium cannot handle. As per the Same Origin Policy your javascript(Selenium tests/testrunner) cannot run/access content that is on a &lt;em&gt;&lt;strong&gt;different domain, protocol or port&lt;/strong&gt;&lt;/em&gt;. If you still would like to use Selenium you have to use the experimental modes (chrome for Firefox or hta for IE) which are really beta and flaky. &lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;So having thrown that out of consideration we had to run tests from the same machine as the application under test(AUT). &lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;We decided to go with Selenium core.(since Selenium RC for some reason stripped our pages of css - ugh?) &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;To do this we installed Selenium core in our application code ie in the public directory(since ours is a ruby app - for a regular java app in apache tomcat for example webapps would be the equivalent location). Then we could run TestRunner with our TestSuite and fire the tests.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;The next step was to automate all this testing so that it runs periodically and runs as part of a build so that your application is functionally tested continuously. &lt;/span&gt;&lt;/p&gt;Some details you would like to note before we dig deeper.&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;Selenium core just runs as a url :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;Our URL was as follows&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;span style="font-family:courier new;"&gt;http://localhost:3000/selenium/core/TestRunner.html?test=../tests/TestSuite.html&amp;auto=true&amp;amp;resultsUrl=http://localhost:3000/postResults?browser=ie6&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;This URL does a few things - &lt;/span&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;it specifies a test suite TestSuite.html&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;that the tests are going to run automatically (basically as soon as you point your browser to the above URL that is)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;they are going to post results to a results URL. &lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;All this is well documented. What is not documented clearly is that one needs to write a POST handler (our POST handler is at http://localhost:3000/postResults). This could be the hard one if a non-developer is trying to set this thing up.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;I have written a quick and dirty one in ruby which I will post here for reference&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;class PostResultsController &amp;lt; ApplicationController&lt;br /&gt;def index&lt;br /&gt;browser_name = params["browser"]&lt;br /&gt;time = Time.now&lt;br /&gt;timestamp = "#{time.month}/#{time.day}/#{time.year} #{time.hour}:#{time.min}:#{time.sec}"&lt;br /&gt;results_file_name = "public/results/#{browser_name}(#{timestamp})-results.html"&lt;br /&gt;&lt;br /&gt;f = File.new(results_file_name, "w+")&lt;br /&gt;# f.write(params)&lt;br /&gt;&lt;br /&gt;f.write("&amp;lt;html&amp;gt;&amp;lt;LINK href='selenium-test.css' type=text/css rel=stylesheet&amp;gt;&amp;lt;body&amp;gt;")&lt;br /&gt;result = params["result"]&lt;br /&gt;f.write("&amp;lt;table&amp;gt;")&lt;br /&gt;&lt;br /&gt;f.write("&amp;lt;tr&amp;gt;")&lt;br /&gt;f.write("&amp;lt;td&amp;gt;Result : #{result}&amp;lt;/td&amp;gt;")&lt;br /&gt;numTestTotal = params["numTestTotal"]&lt;br /&gt;f.write("&amp;lt;td&amp;gt;Tests Total : #{numTestTotal}&amp;lt;/td&amp;gt;")&lt;br /&gt;f.write("&amp;lt;/tr&amp;gt;")&lt;br /&gt;&lt;br /&gt;f.write("&amp;lt;tr&amp;gt;")&lt;br /&gt;totalTime = params["totalTime"]&lt;br /&gt;f.write("&amp;lt;td&amp;gt;Total Time : #{totalTime}secs.&amp;lt;/td&amp;gt;")&lt;br /&gt;f.write("&amp;lt;/tr&amp;gt;")&lt;br /&gt;&lt;br /&gt;f.write("&amp;lt;tr&amp;gt;")&lt;br /&gt;num_test_passes = params["numTestPasses"]&lt;br /&gt;f.write("&amp;lt;td&amp;gt;Tests Passed : #{num_test_passes}&amp;lt;/td&amp;gt;")&lt;br /&gt;num_command_passes = params["numCommandPasses"]&lt;br /&gt;f.write("&amp;lt;td&amp;gt;Commands Passed : #{num_command_passes}&amp;lt;/td&amp;gt;")&lt;br /&gt;f.write("&amp;lt;/tr&amp;gt;")&lt;br /&gt;&lt;br /&gt;f.write("&amp;lt;tr&amp;gt;")&lt;br /&gt;numTestFailures = params["numTestFailures"]&lt;br /&gt;f.write("&amp;lt;td&amp;gt;Tests Failed : #{numTestFailures}&amp;lt;/td&amp;gt;")&lt;br /&gt;numCommandFailures = params["numCommandFailures"]&lt;br /&gt;f.write("&amp;lt;td&amp;gt;Commands Failed : #{numCommandFailures}&amp;lt;/td&amp;gt;")&lt;br /&gt;numCommandErrors = params["numCommandErrors"]&lt;br /&gt;f.write("&amp;lt;td&amp;gt;Commands Errored : #{numCommandErrors}&amp;lt;/td&amp;gt;")&lt;br /&gt;f.write("&amp;lt;/tr&amp;gt;")&lt;br /&gt;f.write("&amp;lt;/table&amp;gt;")&lt;br /&gt;totalTests = params["numTestTotal"].to_i - 1&lt;br /&gt;for i in 1..totalTests&lt;br /&gt;index_str = 'testTable.' + i.to_s&lt;br /&gt;testTable = params[index_str]&lt;br /&gt;f.write(testTable)&lt;br /&gt;end&lt;br /&gt;f.write("&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;")&lt;br /&gt;f.close&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;end&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;Another thing that I did not allude to was the browser=ie6 parameter on the results URL. This was another requirement for our scripts -that they be run in 6 different browsers and post results for us to look at. That means I have to know for each test what I am running against and this extra parameter on the resultsURL would be nice to have. &lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;To make sure Selenium understood it I had to change selenium-test-runner.js as follows&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;add the following to HtmlTestRunnerControlPanel prototype&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier;"&gt;getBrowser: function() {&lt;br /&gt;return this._getQueryParameter("browser");&lt;br /&gt;},&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;and then use it in TestResult prototype like so&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier;"&gt;//added getBrowser so that we can run tests on a browser and send the browser name with results.&lt;br /&gt;var browser = this.controlPanel.getBrowser();&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If this is not enough Selenium also adds a constraint on how you automate using cruisecontrol. The only way to do that is to fire the browser for test with the URL like above. So cruisecontrol has to take the help of a batch file to automate this - which is less than ideal. &lt;/p&gt;&lt;p&gt;Cruisecontrol by design waits for the build tasks to complete(in this case the batch file). But as the tests run inside the browser Cruise has no way to know after they have finished as browser does not change state. &lt;/p&gt;&lt;p&gt;We had to do something like this in our batch file&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;set PATH = %PATH%;path_to_ie&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;start iexplore.exe selenium_url_like_above&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;rem approx wait of 60secs hack &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;ping -n 61 127.0.0.1 &amp;gt; nul&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;taskkill /F /IM iexplore.exe&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;This batch file above will set the path so that IE can be run. then 'start' the browser in a separate process then wait for 60 secs and then kill IE. Once IE is killed the batch process is over and cruise can wakeup.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;You can automate running Selenium tests for any browser as shown above. Just make sure your ping interval is set to appropriate time so that the browser is closed only after the tests are done not before.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;(A good reference for batch files and command prompt automation is - &lt;a href="http://www.allenware.com/icsw/icswidx.htm"&gt;http://www.allenware.com/icsw/icswidx.htm&lt;/a&gt;. I found the info for 'start' and the hack for sleep using ping here)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;2 more hacks are on my mind but I will post in a later discussion.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;Phew! This has been my first blog post in a long time. Thanks for the patience.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-3357270080279177219?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/3357270080279177219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=3357270080279177219' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/3357270080279177219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/3357270080279177219'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2007/03/automated-testing-and-continuous.html' title='Automated Testing and Continuous Integration with Selenium'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-4806950032633251368</id><published>2006-12-16T10:30:00.000-08:00</published><updated>2006-12-16T11:20:50.960-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='User Centered Design'/><category scheme='http://www.blogger.com/atom/ns#' term='UCD'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='errors'/><title type='text'>Don't show errors  - Prevent them</title><content type='html'>One of my colleagues &lt;a href="http://josh.ev9.org/weblog/"&gt;Josh Evnin&lt;/a&gt; recently did a User Centered Design study for the application we are building at a client.&lt;br /&gt;&lt;br /&gt;We were trying to build a web application where the user interacts with the system using the well known html forms.&lt;br /&gt;We were doing the traditional form validation where the user is required to enter information/select the required fields.&lt;br /&gt;When the user clicks submit the application does a validation routine and displays errors next to the error fields.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_99A2NrVKgk8/RYQ76LBUeSI/AAAAAAAAAAM/Nx_Po2FzYbI/s1600-h/errors.PNG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5009194556119611682" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_99A2NrVKgk8/RYQ76LBUeSI/AAAAAAAAAAM/Nx_Po2FzYbI/s320/errors.PNG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;This is one way to make sure that no erratic information enters the application. I would call this method as 'trial and error'.&lt;br /&gt;&lt;br /&gt;With the new UCD that Josh came up with  - he gave a new direction of thought to error handling and error perception to the user.&lt;br /&gt;&lt;br /&gt;The philosophy was why let the user make an error and submit in the first place.&lt;br /&gt;Why not just stop the user from submitting ?  - (by being more proactive) - that way the user already knows something is missing and he needsto fill out/select the required fields or else he will not be able to proceed.&lt;br /&gt;&lt;br /&gt;Essentially what my UCD expert wants to tell me is why let the user get into error conditions at all.&lt;br /&gt;I as a developer think -Let's do preventive design and minimise the number of round trips to the server and make sure only valid data gets to the server in the first place.&lt;br /&gt;&lt;br /&gt;This saves me not only the time to build code for all the errors that the server gets and also adds confusion to my user.  (Also I should mention that all the analysts on the project had their own opinions about the error text that should go on the page - but that is a funnier discussion in its own right)&lt;br /&gt;&lt;br /&gt;The new design of the above page would look and behave as shown below.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_99A2NrVKgk8/RYQ8FLBUeTI/AAAAAAAAAAU/5DNOLMicBB4/s1600-h/noerrors2.PNG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5009194745098172722" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_99A2NrVKgk8/RYQ8FLBUeTI/AAAAAAAAAAU/5DNOLMicBB4/s320/noerrors2.PNG" border="0" /&gt;&lt;/a&gt; &lt;a href="http://2.bp.blogspot.com/_99A2NrVKgk8/RYQ8J7BUeUI/AAAAAAAAAAc/nPjTtZKditg/s1600-h/noerrors1.PNG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5009194826702551362" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_99A2NrVKgk8/RYQ8J7BUeUI/AAAAAAAAAAc/nPjTtZKditg/s320/noerrors1.PNG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Notice the difference.&lt;br /&gt;As a developer I don't have to use server side validation - which at most times is desired - also with the different types of validation required today the number/string validation that comes standard with frameworks is hardly of any use. So I write my own regex based validation in javascript anyway.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As a user - this is what is more pleasing because I know that I have not completed this page correctly till the submit button is clickable.&lt;br /&gt;&lt;br /&gt;Some sugar around training/informative messages on the screen make the screen more friendly to the user.&lt;br /&gt;&lt;br /&gt;Get your Agile UI/UCD/Human Computer Interaction earlier in the game... and make friends with him/her..- It can save u a lot of code and make the application look slick....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-4806950032633251368?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/4806950032633251368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=4806950032633251368' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/4806950032633251368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/4806950032633251368'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2006/12/dont-show-errors-prevent-them.html' title='Don&apos;t show errors  - Prevent them'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_99A2NrVKgk8/RYQ76LBUeSI/AAAAAAAAAAM/Nx_Po2FzYbI/s72-c/errors.PNG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-8185399910801667781</id><published>2006-11-22T17:35:00.000-08:00</published><updated>2006-12-02T09:08:48.078-08:00</updated><title type='text'>How to write a blog</title><content type='html'>I follow Seth's blog. He has a short post about &lt;a href="http://sethgodin.typepad.com/seths_blog/2006/11/how_to_write_a_.html"&gt;writing a blog post&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-8185399910801667781?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/8185399910801667781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=8185399910801667781' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/8185399910801667781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/8185399910801667781'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2006/11/how-to-write-blog.html' title='How to write a blog'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37105559.post-116261259241539190</id><published>2006-11-03T19:41:00.000-08:00</published><updated>2006-11-03T19:56:32.423-08:00</updated><title type='text'>who are we creating software for?</title><content type='html'>who are the users of an apple imac, an ipod, a bluetooth phone, a laptop with a dual core processor? - do all of these have to be designed for your granma?&lt;br /&gt;&lt;br /&gt;if you glance over the types of users for these hitech devices - or applications - it is the techno savvy college going/graduated individuals. Not many granmas actually own a computer or would like to own an ipod to listen to music. If your granma is anything like my granma (I bet she is) she would be happy with a radio or a record player or a TV that plays decent programs.&lt;br /&gt;&lt;br /&gt;so why should we build everything that is good for my granma. I think I would build each of the above based on what my intelligent user - who is different if slightly so in each case - needs. An Ipod - as it is rightly so - is for the active user who travels to college,  to work, is in the gym for 2 hours a day etc.&lt;br /&gt;A laptop with dual core is useless for viewing pictures or checking email - that my granma does.&lt;br /&gt;&lt;br /&gt;Point to be noted - Don't think about your granma when u design something&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37105559-116261259241539190?l=betarelease.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://betarelease.blogspot.com/feeds/116261259241539190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37105559&amp;postID=116261259241539190' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/116261259241539190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37105559/posts/default/116261259241539190'/><link rel='alternate' type='text/html' href='http://betarelease.blogspot.com/2006/11/who-are-we-creating-software-for.html' title='who are we creating software for?'/><author><name>Sudhindra Rao</name><uri>http://www.blogger.com/profile/07437146809844632919</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
