<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>if(is_geek)... &#187; Programming</title>
	<atom:link href="http://www.ifisgeek.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ifisgeek.com</link>
	<description>Look! A New Doot!</description>
	<lastBuildDate>Thu, 03 Sep 2009 04:51:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Does Usability Really Matter?</title>
		<link>http://www.ifisgeek.com/2009/09/02/does-usability-really-matter/</link>
		<comments>http://www.ifisgeek.com/2009/09/02/does-usability-really-matter/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 04:51:49 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=265</guid>
		<description><![CDATA[I&#8217;ll be the first to admit that I am not a usability expert and, in general, I think that there is too much talk about usability with little real benefit. However, as a good computer scientist, I believe that it is an important part of software engineering. There are people who know a hell of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be the first to admit that I am not a usability expert and, in general, I think that there is too much talk about usability with little real benefit. However, as a good computer scientist, I believe that it is an important part of software engineering. There are people who know a hell of a lot about it and I tend to rely on them to make the appropriate decisions regarding how I should be making my software more usable. This is quite odd. In most other aspects of development, I like to question things and learn the bits I don&#8217;t know very well. When it comes to usability, however, I have always been happy to let someone else do the thinking.</p>
<div style="float:right;padding:10px;"><a href="http://www.ifisgeek.com/wp-content/uploads/IMG_3662.JPG" target="_blank"><img src="http://www.ifisgeek.com/wp-content/uploads/IMG_3662.JPG" alt="Devices" title="Devices" width="300" height="225" class="alignnone size-medium wp-image-266" border="0" /></a></div>
<p>Recently though, I have started to pay more attention to usability &#8211; in software and in other aspects of life. The image to the right is of my television and associated devices (apologies for the blur). I was looking at this tonight and I started wondering why those of us who work with software are so concerned with usability when it seems like no one else is. Let&#8217;s take a look at the various indicator lights that are visible in this picture. First off, there&#8217;s my Wii. It is in standby mode and is displaying an amber light. That makes sense, right? It&#8217;s not fully on and not fully off. So, amber indicates standby. Below that is my stereo receiver. It is on and has a green light on it. Again, this makes logical sense. Then there is my TV. It is on but it sports a <em>red</em> light to indicate the on state. Finally, in the lower right is my satellite receiver which has both a green and an amber light on it. This would seem to indicate a state somewhere between standby and on, but the device is fully on.</p>
<p>So, has a single sale of one of these devices ever been lost due to the lack of usability the indicator lights represent? I highly doubt it. I also don&#8217;t know anyone who has ever test-driven a television&#8217;s menus before purchase. Sure, we probably see the menus when the sales guy is talking to us about resolution and contrast ratio, but we&#8217;re not paying attention to that. We completely ignore the usability aspects of these common items because we are more concerned with how well the device does its primary function. In the case of a television, we only care about how good the picture looks.</p>
<p>Why then do we as software developers hold ourselves, in theory anyway, to such a higher standard? Why is usability so much more important with software than other products? Could it be a hold over from the days when there was resistance to computers from older generations? Perhaps when there was widespread resistance to anything to do with computers there was a much greater need to make the applications on the computers so amazingly easy to use in order for their benefit to be readily apparent. If so, do we still need to try so hard?</p>
<p>Perhaps it has nothing to do with the user and everything to do with the software. With non-software items it is usually very easy to describe what they do in a short sentence. What does your television do? It allows me to watch shows and movies. What does your razor do? It shaves my facial hair. Now, think about the software you use. Can you easily describe the function of the software the same? Firefox lets me view web pages. It also lets me search Google. It shows me videos. It plays Flash games. The list goes on. Could usability be a problem for software because we are simply trying to jam too much functionality into our applications?</p>
<p>There is an example from the non-software world which makes me think this might be the case. Think of a Swiss Army Knife. You can&#8217;t easily describe all of its functions in a single sentence. You also cannot say that the damn thing is in any way a usability success. It is a pain in the ass to use, but it saves you from carrying more stuff. Maybe the answer to software usability is not massive amounts of research and testing to make a Swiss Army Knife application a little more usable. Maybe the answer is to make our applications simpler and make more of them. The popularity of gadgets/widgets and the thousands of wee little Facebook applications could be an indication that this is true.</p>
<p>I don&#8217;t know if any of this is really relevant to a discussion on usability, but it is the way things look to me. I have many powerful applications on my computer, but I do tend to prefer using a dashboard widget if available. I tend to frequent websites that focus on one thing and do it really well. It might very well be that what we perceive as usability issues are just a case of Jack of all trades, master of none. If anyone more enlightened on the subject that me has some additional insights, please leave me some comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/09/02/does-usability-really-matter/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Running JSLint in Automated Build Scripts</title>
		<link>http://www.ifisgeek.com/2009/05/05/running-jslint-in-automated-build-scripts/</link>
		<comments>http://www.ifisgeek.com/2009/05/05/running-jslint-in-automated-build-scripts/#comments</comments>
		<pubDate>Tue, 05 May 2009 18:29:14 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[VendAsta]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[build scripts]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=224</guid>
		<description><![CDATA[At VendAsta we use automated build scripts and a TeamCity server for continuous integration. Whenever someone commits code to a project, a whole suite of automated build targets are run against the code base to check things like unit tests, python syntax (via pylint) and code coverage. One thing that was missing from the mix [...]]]></description>
			<content:encoded><![CDATA[<p>At <a href="http://www.vendasta.com">VendAsta</a> we use automated build scripts and a <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> server for continuous integration. Whenever someone commits code to a project, a whole suite of automated build targets are run against the code base to check things like unit tests, python syntax (via pylint) and code coverage. One thing that was missing from the mix was the automated running of jslint to check the syntax of our ever-increasing corpus of JavaScript code. As it turns out, adding this to our ANT targets wasn&#8217;t all that difficult.</p>
<p>The only real difficulty you are likely to encounter in creating a JSLint target for your build scripts is that JSLint is, itself, written in JavaScript. Other helpful libraries such as JSMin or the YUICompressor from Yahoo are distributed as jar files and can be executed easily with an <code>exec</code> block with the executable set to java. With JSLint, however, you are going to need a JavaScript engine which you can execute from the command line in order to run the JSLint script to validate your JavaScript code. THis actually sounds harder than it is.</p>
<p>For our implementation, I chose to use the <a href="http://www.mozilla.org/rhino/">Rhino</a> engine since there is documented support for JSLint on it, and even a handy helper file to include in your system: <a href="http://www.JSLint.com/rhino/rhino.js">rhino.js</a>. Grab a copy of Rhino (the actual file you&#8217;ll want to include is js.jar), the Rhino helper script I just mentioned and <a href="http://www.JSLint.com/fulljslint.js">JSLint itself</a>. Place them all together into some sort of tools directory in your project. Ours is located in /tools/ant.</p>
<p>Now comes the fun part, writing the actual target in ANT. For our purposes, we want to process all .js files contained in a particular location, as defined in a build property called <code>jsdir</code>. We also want to ignore any files that are contained in a vendor subdirectory of <code>jsdir</code>, as we should not need to worry about third-party scripts that don&#8217;t pass JSLint. Let&#8217;s get things started with our basic, empty target:</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- </span>
<span style="color: #808080; font-style: italic;">jslint - Runs lint checks on js files</span>
<span style="color: #808080; font-style: italic;">--&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jslint&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h5>Listing 1: The basic, empty jslint target</h5>
</p>
<p>Within the target there are two things we are going to need. First a way to reference all of the files we want to operate over and second, the actual call to run JSLint on those files. For the first requirement we&#8217;ll use a <code>pathconvert</code> tag with a nested <code>fileset</code>. The <code>pathconvert</code> will allow us to generate a space-separated list of files and stuff that into a property which we&#8217;ll call <code>jsfiles</code>. The <code>fileset</code> block will do the actual work of finding the files in question. It will operate over <code>${jsdir}</code> including all .js files and excluding all .js files in the vendor subdirectory. Listing 2 shows the <code>pathconvert</code> block added to our empty target.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- </span>
<span style="color: #808080; font-style: italic;">jslint - Runs lint checks on js files</span>
<span style="color: #808080; font-style: italic;">--&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jslint&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pathconvert</span> <span style="color: #000066;">pathsep</span>=<span style="color: #ff0000;">&quot; &quot;</span> <span style="color: #000066;">property</span>=<span style="color: #ff0000;">&quot;jsfiles&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${jsdir}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;**/*.js&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclude</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;vendor/**/*.js&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fileset<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pathconvert<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h5>Listing 2: The <code>pathconvert</code> block added to our target.</h5>
</p>
<p>Finally, it is time to add the actual call to JSLint. To allow our build scripts to work for multiple projects, we have pushed as much information into properties that get defined in project-specific files as possible. The location of the Rhino jar (js.jar) is placed into the property <code>js.jar</code> and the location of the JSLint script (jslint.js) is placed into the property <code>jslint.js</code>. With those properties suitably defined elsewhere, we have the final piece of our puzzle: the <code>exec</code> block. We have the executable set to java and failonerror set to true, so that our target will appropriately fail when JSLint fails to give our code a passing grade. The final target, including the <code>exec</code> block can be seen in listing 3.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- </span>
<span style="color: #808080; font-style: italic;">jslint - Runs lint checks on js files</span>
<span style="color: #808080; font-style: italic;">--&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jslint&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pathconvert</span> <span style="color: #000066;">pathsep</span>=<span style="color: #ff0000;">&quot; &quot;</span> <span style="color: #000066;">property</span>=<span style="color: #ff0000;">&quot;jsfiles&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${jsdir}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;**/*.js&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclude</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;vendor/**/*.js&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fileset<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pathconvert<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exec</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${jsdir}&quot;</span> <span style="color: #000066;">executable</span>=<span style="color: #ff0000;">&quot;java&quot;</span> <span style="color: #000066;">failonerror</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">line</span>=<span style="color: #ff0000;">&quot;-jar ${js.jar} ${jslint.js} ${jsfiles}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exec<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h5>Listing 3: The final target.</h5>
</p>
<p>Put all together, the <code>pathconvert</code> block stuffs the list of files to work on into the property <code>${jsfiles}</code> which is then passed as an argument to the jslint.js file. The jslint.js file is itself the first argument passed to the Rhino JavaScript engine (js.jar) which is run directly by java. Running your <code>ant jslint</code> target should give you some nice feedback on the syntax of your JavaScript code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/05/05/running-jslint-in-automated-build-scripts/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>25 Things About Me</title>
		<link>http://www.ifisgeek.com/2009/02/06/25-things-about-me/</link>
		<comments>http://www.ifisgeek.com/2009/02/06/25-things-about-me/#comments</comments>
		<pubDate>Sat, 07 Feb 2009 04:29:44 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Atheism]]></category>
		<category><![CDATA[Family]]></category>
		<category><![CDATA[Gaming]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Politics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Lists]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Me]]></category>
		<category><![CDATA[Music]]></category>
		<category><![CDATA[Scotland]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=196</guid>
		<description><![CDATA[Rules: Once you&#8217;ve been tagged, you are supposed to write a note with 25 random things, facts, habits, or goals about you. At the end, choose 25 people to be tagged. You have to tag the person who tagged you.
If I tagged you, it&#8217;s because I want to know more about you!
(To do this, go [...]]]></description>
			<content:encoded><![CDATA[<p>Rules: Once you&#8217;ve been tagged, you are supposed to write a note with 25 random things, facts, habits, or goals about you. At the end, choose 25 people to be tagged. You have to tag the person who tagged you.</p>
<p>If I tagged you, it&#8217;s because I want to know more about you!</p>
<p>(To do this, go to “notes” under tabs on your profile page, paste these instructions in the body of the note, type your 25 random things, tag 25 people (in the right hand corner of the app) then click publish.)</p>
<ol>
<li>I was born in Nova Scotia</li>
<li>I have never felt more at ease than when I was in Scotland</li>
<li>I am going to Mexico in 22 days</li>
<li>I miss making music</li>
<li>I like it loud</li>
<li>Except when I don&#8217;t</li>
<li>I am a solid convert &#8211; to Macs</li>
<li>I am a proud Atheist</li>
<li>I usually need spell check to spell Atheist correctly</li>
<li>I love sci-fi</li>
<li>I have an awesome family</li>
<li>Boxer briefs</li>
<li>I love chick-rock</li>
<li>I might be an author today if not for one English teacher</li>
<li>I miss writing</li>
<li>I actually enjoy programming</li>
<li>I hate to admit it but I dig Lindsay&#8217;s One Gossip Tree Girl shows</li>
<li>I am a whore for documentaries</li>
<li>I am intrigued by Eve online</li>
<li>I miss playing WoW</li>
<li>I am an introvert&#8230;</li>
<li>&#8230;but I fake extrovert fairly well&#8230;</li>
<li>&#8230;or maybe I&#8217;m bipolar</li>
<li>I think I could do a better job than our Government or any of the lame other parties we have</li>
<li>I wish I could spend more time with my wife and daughter.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/02/06/25-things-about-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Monitor and Manage Your Rep With StepRep</title>
		<link>http://www.ifisgeek.com/2009/01/27/monitor-and-manage-your-rep-with-steprep/</link>
		<comments>http://www.ifisgeek.com/2009/01/27/monitor-and-manage-your-rep-with-steprep/#comments</comments>
		<pubDate>Wed, 28 Jan 2009 04:01:37 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Teh Intertubes]]></category>
		<category><![CDATA[VendAsta]]></category>
		<category><![CDATA[MyFrontSteps]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[StepRep]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=190</guid>
		<description><![CDATA[I work with an amazing group of people. The project I am working on is called MyFrontSteps which is a social media application for getting and sharing ]]></description>
			<content:encoded><![CDATA[<p>I work with an amazing group of people. The project I am working on is called <a href="http://ww.myfrontsteps.com">MyFrontSteps</a> which is a social media application for getting and sharing <a href="http://www.myfrontsteps.com>Home Inspiration<a/> and <a href="http://www.myfrontsteps.com">Trusted Referrals</a> to service providers in your area. We&#8217;re working on some pretty challenging stuff and, even though we are progressing rapidly, we are not quite to the point where we have anything public-beta worthy. Our colleagues at the far end of the building, the <a href="http://steprep.myfrontsteps.com">StepRep</a> team, <em>have</em> reached their public beta and it is really impressive!</p>
<p>Whereas the side of the project I work on is focused on dealing with home owners, StepRep is a tool for <a href="http://steprep.myfrontsteps.com">Online Reputation Management</a>, primarily targeted at the service providers that our system will help you recommend to your friends. Of course, it isn&#8217;t just people in the home improvement or real estate industries that have online reputations they need to manage. In fact, software developers and hardcore geeks have online reputations! <em>I</em> have an online reputation! That&#8217;s why I signed up for the beta at <a href="http://steprep.myfrontsteps.com">http://steprep.myfrontsteps.com</a>. I know that I am a little biased by the fact that I work with the people that developed all of this, but I am very impressed with what they have done. From a technical standpoint there is a lot going on that even I find overwhelming and a little &#8220;magical&#8221;.</p>
<div class="right_cutout">
<h4>My Personal StepRep Widget</h4>
<div style="text-align: center;"><iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://steprep.myfrontsteps.com/widget/v1?id=63c492ec3fdfc4499cdbe30b3e15f92e&#038;bgColor=eeeeee&#038;borderColor=000000&#038;fontColor=111111&#038;linkColor=222222&#038;vlinkColor=333333&#038;title=My%20StepRep%20Widget&#038;size=small" width="185" height="314"></iframe>
<div><a href="http://steprep.myfrontsteps.com/Saskatoon/Communications-Networking/Computers-Electronics-Internet/Jeffery-Read">Jeffery Read</a></div>
</div>
</div>
<p>The main purpose of StepRep is to allow you to see what people are saying about you and your business on the Internet. This includes anywhere and everywhere that someone might be talking about you. StepRep presents you with this information and allows you to categorize the items as good or bad. The good ones are things that you can use to convince new people that you are the right choice for the work they need done. You can even place these items into a widget that can be slapped on your company website, your personal blog &#8211; anywhere you want to trumpet your achievements and build your reputation. As for the items you think reflect poorly on you, well, obviously you wouldn&#8217;t want to put them in your widget, but you can see where past customers might not have been completely satisfied and do something to change their mind. Flip them to a positive and then slap them in your widget for all to see.</p>
<p>I won&#8217;t even try to discuss anything about how StepRep does what it does so well. Honestly, this is because I don&#8217;t understand a lot of it. The team working on it are very smart and very skilled at what they do. Starting with the next development sprint my team is going to be working closely with that team as we bring the two systems together to help service providers reach a wider audience through the friends of their customers and to help home owners find the best service providers through people they trust. It&#8217;s going to be very exciting and I am hoping that I&#8217;ll be able to learn a few things about how StepRep works.</p>
<p>One last thing I want to mention is how much I love the design work that was done for the StepRep site. I got to see some preliminary designs for the MyFrontSteps site today as well and they blew me away. Marie-Louise has really done an awesome job. This is something I really love about working at VendAsta. I work with people who are very skilled at designing for the web and for maximum usability. The wireframing, mockups and designs that I have seen done in my short time there have amazed me. I came to VendAsta from a company that had plenty of graphic designers in the Marketing department. They were all firmly rooted in the world of print advertising. There were some definite growing pains going on as they started to embrace the new world of web design. Now I am working with people who understand the web and the best practices for developing rich, engaging applications for the web. It&#8217;s freaking awesome!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/01/27/monitor-and-manage-your-rep-with-steprep/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Splitting Django Models Into Separate Files</title>
		<link>http://www.ifisgeek.com/2009/01/26/splitting-django-models-into-separate-files/</link>
		<comments>http://www.ifisgeek.com/2009/01/26/splitting-django-models-into-separate-files/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 04:16:38 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[VendAsta]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=182</guid>
		<description><![CDATA[A little while ago I wrote a post about getting Django unittests to work on DreamHost. The particular problem with the DreamHost setup is that they don&#8217;t allow you to programmatically create and drop databases and the default Django unittest behaviour is to do just that: create a brand new test db, use it and [...]]]></description>
			<content:encoded><![CDATA[<p>A little while ago I wrote a post about <a href="http://www.ifisgeek.com/2008/12/27/django-unittesting-on-dreamhost/">getting Django unittests to work on DreamHost</a>. The particular problem with the DreamHost setup is that they don&#8217;t allow you to programmatically create and drop databases and the default Django unittest behaviour is to do just that: create a brand new test db, use it and then drop it. Since I wrote that post I have begun migrating all of my domains away from DreamHost but I have still found that technique to be useful with new projects.</p>
<p>I first started using Django when I started at VendAsta and this issue didn&#8217;t creep up there because we are use Google App Engine and its DataStore on the backend instead of a traditional database. With no database there was no issue with creating/dropping anything. It was only when I started using Django on my own that I came across that problem. There was one more issue with Django that I came across only when I started doing things outside of work: Django expects all of your models to be in a single file called models.py. I hate that. A lot.</p>
<p>I did some googling about the problem and found that there were a bunch of other people who didn&#8217;t like it much either. There were a few solutions but they all involved manually mucking about with the __all__ attribute in the __init__.py file of your models directory. Sure, it works, but I don&#8217;t like having to define a model in two places to use it. Oddly enough it was in some test code at work that I found the answer.</p>
<p>For our project at VendAsta we are using the Django App Engine Helper to provide a nice easy interface to the DataStore on the backend. A part of this is a small __init__.py file which allows you to spread your tests out in multiple files. Django likes its tests to be in a single tests.py file just like it likes its models to be in models.py. The wee bit of Google code is shown in Listing 1.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python2.4</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Copyright 2008 Google Inc.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span>
<span style="color: #808080; font-style: italic;"># you may not use this file except in compliance with the License.</span>
<span style="color: #808080; font-style: italic;"># You may obtain a copy of the License at</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;">#     http://www.apache.org/licenses/LICENSE-2.0</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Unless required by applicable law or agreed to in writing, software</span>
<span style="color: #808080; font-style: italic;"># distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span>
<span style="color: #808080; font-style: italic;"># WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span>
<span style="color: #808080; font-style: italic;"># See the License for the specific language governing permissions and</span>
<span style="color: #808080; font-style: italic;"># limitations under the License.</span>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Loads all the _test.py files into the top level of the package.
&nbsp;
This file is a hack around the fact that Django expects the tests &quot;module&quot; to
be a single tests.py file and cannot handle a tests package inside an
application.
&nbsp;
All _test.py files inside this package are imported and any classes derived
from unittest.TestCase are then referenced from this file itself so that they
appear at the top level of the tests &quot;module&quot; that Django will import.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">types</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
PACKAGE = <span style="color: #483d8b;">'appname.tests'</span>
TEST_RE = r<span style="color: #483d8b;">&quot;^.*_test.py$&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Search through every file inside this package.</span>
test_names = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
test_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span> __file__<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>test_dir<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>TEST_RE, filename<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">continue</span>
  <span style="color: #808080; font-style: italic;"># Import the test file and find all TestClass clases inside it.</span>
  test_module = <span style="color: #008000;">__import__</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s.%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>PACKAGE, filename<span style="color: black;">&#91;</span>:-3<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, 
                           <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>,
                           filename<span style="color: black;">&#91;</span>:-3<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>test_module<span style="color: black;">&#41;</span>:
    item = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>test_module, name<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: black;">&#40;</span><span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>item, <span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, <span style="color: #dc143c;">types</span>.<span style="color: black;">ClassType</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span>
            <span style="color: #008000;">issubclass</span><span style="color: black;">&#40;</span>item, <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
      <span style="color: #ff7700;font-weight:bold;">continue</span>
    <span style="color: #808080; font-style: italic;"># Found a test, bring into the module namespace.</span>
    <span style="color: #ff7700;font-weight:bold;">exec</span> <span style="color: #483d8b;">&quot;%s = item&quot;</span> <span style="color: #66cc66;">%</span> name
    test_names.<span style="color: black;">append</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Hide everything other than the test cases from other modules.</span>
__all__ = test_names</pre></td></tr></table></div>

<h5>Listing 1: __init__.py file from Google for a tests module</h5>
</p>
<p>Essentially what this file does is loop through all files in the same directory and for each on that matches the pattern listed on line 40 (in this case, files that end in &#8216;_test.py&#8217;) and import all of the Classes from those files that are subclasses of the TestCase class. Finally, the code on line 62 does the magic with __all__ that I wanted to avoid doing manually for my models. It was this line that caught my attention and started me wondering if this code could be used for spreading models across multiple files.</p>
<p>In order for this to work for models there are a few things that need to be changed. First of all, on line 40, the pattern should be changed to match on *.py to grab all of the python files in the directory. Then, on line 46, add<br />
<blockquote> or filename == &#8220;__init__.py&#8221;</p></blockquote>
<p> to ensure that we don&#8217;t try to import the file we are in. Finally, remove the subclass requirement from line 55, as we are just concerned with importing classes here not what they inherit from. Putting it all together results in Listing 2. Place that in the __init__.py of a directory called models and you&#8217;ll not have to manually manage the __all__ list for your models in separate files.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python2.4</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">types</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
PACKAGE = <span style="color: #483d8b;">'my_app.models'</span>
MODEL_RE = r<span style="color: #483d8b;">&quot;^.*.py$&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Search through every file inside this package.</span>
model_names = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
model_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span> __file__<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>model_dir<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>MODEL_RE, filename<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> filename == <span style="color: #483d8b;">&quot;__init__.py&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">continue</span>
  <span style="color: #808080; font-style: italic;"># Import the model file and find all clases inside it.</span>
  model_module = <span style="color: #008000;">__import__</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s.%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>PACKAGE, filename<span style="color: black;">&#91;</span>:-3<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>,
                           <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>,
                           filename<span style="color: black;">&#91;</span>:-3<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>model_module<span style="color: black;">&#41;</span>:
    item = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>model_module, name<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>item, <span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, <span style="color: #dc143c;">types</span>.<span style="color: black;">ClassType</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
      <span style="color: #ff7700;font-weight:bold;">continue</span>
    <span style="color: #808080; font-style: italic;"># Found a model, bring into the module namespace.</span>
    <span style="color: #ff7700;font-weight:bold;">exec</span> <span style="color: #483d8b;">&quot;%s = item&quot;</span> <span style="color: #66cc66;">%</span> name
    model_names.<span style="color: black;">append</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Hide everything other than the classes from other modules.</span>
__all__ = model_names</pre></td></tr></table></div>

<h5>Listing 2: __init__.py file modified for a models module</h5>
</p>
<p>Now, there is one last thing that you are going to need to do in order for everything to run properly in Django. It is a very simple addition to the end of each of your classes. I have seem some people complaining about the need to do this in various forums, but honestly, if you are using any form of modern text editing application, it should only take you about 2 minutes to create a new template for a model that has the little piece of code shown in Listing 3 at the bottom of the class (replace your_app_name with your actual app name).</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        <span style="color: #483d8b;">&quot;&quot;&quot;Meta Class for your model.&quot;&quot;&quot;</span>
        app_label = <span style="color: #483d8b;">'your_app_name'</span></pre></td></tr></table></div>

<h5>Listing 3: Meta class required at the end of each model for proper functioning.</h5></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/01/26/splitting-django-models-into-separate-files/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Reflections on MFS Sprint 1</title>
		<link>http://www.ifisgeek.com/2009/01/06/reflections-on-mfs-sprint-1/</link>
		<comments>http://www.ifisgeek.com/2009/01/06/reflections-on-mfs-sprint-1/#comments</comments>
		<pubDate>Wed, 07 Jan 2009 05:46:36 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[VendAsta]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[Long Way Round]]></category>
		<category><![CDATA[Planning]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=164</guid>
		<description><![CDATA[Today at VendAsta we had our first full day of planning for the MyFrontSteps Sprint #2. We did some high level planning yesterday as well as demoing and a post mortem for the first Sprint. Having had a chance to relax this evening watching a few episodes of Long Way Round with my wife, there [...]]]></description>
			<content:encoded><![CDATA[<p>Today at VendAsta we had our first full day of planning for the MyFrontSteps Sprint #2. We did some high level planning yesterday as well as demoing and a post mortem for the first Sprint. Having had a chance to relax this evening watching a few episodes of Long Way Round with my wife, there are a few things that have struck me about the whole Scrum process as it works at VendAsta.</p>
<p>First and foremost, I absolutely love the amount of planning and forethought that goes into each 30-day development sprint. My past two jobs had nothing that even remotely compares to this. One was an online grocery store (which just recently discontinued operations) which meant that most development was done within the demands of an operating e-business and as a result needed to be very seat-of-the-pants. The other was a manufacturing company which meant that development processes were heavily driven by the demands of sales and manufacturing departments and those demands could and would change in the blink of an eye. Needless to say, I have found the change to be very liberating.</p>
<p>That is not to say that we couldn&#8217;t do more planning. One of the things that we found working through our first sprint was that while we felt we had done a great deal of planning up front, there was actually a lot of granularity that we were lacking. This is something we are endeavoring to overcome in the planning for Sprint 2. As much as I love the planning sessions we are having and as exciting as I find the whole process, it is a very tiring and draining experience. Well worth it, but wearying nonetheless.</p>
<p>A second major thing that struck me was how well we worked as a team. Considering the fact that five people were placed on a development team, given a couple of weeks to do some research and get to know each other and then thrust into the middle of a very ambitious project, we somehow managed to work very well together. Coupling this with the fact that we are working with a large number of cutting edge technologies, I would have expected at least a little friction to develop somewhere in the team over the course of 30 days, but none did. I believe that this is largely due to the environment at VendAsta and their hiring process. Everyone who gets hired there has to go through a lunch with other developers whom they will be working with. If those devs don&#8217;t think that you are a good fit for the team and the company, you don&#8217;t get hired. I don&#8217;t know why more companies don&#8217;t operate this way. People from HR departments should use VendAsta as a case study in how to build a whole company that just &#8220;gels&#8221;.</p>
<p>Finally, in the past two days I have been very impressed with the manner in which some of the trouble spots from Sprint 1 have been discussed. Previously, I have experienced project post mortems that are nothing more than a gathering of people around a table to point fingers at each other. In our post mortem yesterday we were encouraged to be completely honest and frank about what we did and didn&#8217;t like about how Sprint 1 went. At no point was there any finger pointing and the blame game just didn&#8217;t happen. The maturity of my team mates and our &#8220;chickens&#8221; impressed me to no end.</p>
<p>So, that is about it for my impressions on Sprint 1. We&#8217;re neck deep in planning Sprint 2 right now so I am afraid that Episode 4 of Roger&#8217;s Wars will still be a couple of days away. I&#8217;ve had a few people contact me asking when the rest of the saga was going to unfold but with the holidays and now our sprint planning, I&#8217;m having trouble finding the time to do it when my head is not either a) jell-o or b) utterly focused on work. Tomorrow or the next day I hope to sit myself down with a pot of Earl Grey and hammer out the fourth installment. Thanks for your patience <img src='http://www.ifisgeek.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2009/01/06/reflections-on-mfs-sprint-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Django Unittesting on Dreamhost</title>
		<link>http://www.ifisgeek.com/2008/12/27/django-unittesting-on-dreamhost/</link>
		<comments>http://www.ifisgeek.com/2008/12/27/django-unittesting-on-dreamhost/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 04:56:08 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[dreamhost]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=150</guid>
		<description><![CDATA[The default test behaviour for a Django site creates and then destroys a whole test database on each test run. Normally this is not a problem, but the way Dreamhost has their MySQL setup running, the commands to create and drop databases are not available outside of their administration panel. What follows is the solution I have come up with and am currently using to run Django unittests with my Dreamhost MySQL databases.]]></description>
			<content:encoded><![CDATA[<p>Unit testing. It&#8217;s important. We all know that, even if we don&#8217;t practice what we preach. There was zero policy on unit testing at my last job, but now that I have started working at VendAsta, there is plenty of support for proper testing at the highest levels. Now that I am getting back into the habit of writing unit tests for my code at work I have been starting to focus on proper testing for my code at home. Combining Django and hosting with Dreamhost has proven to be a bit of a challenge.
<p>The first hurdle is actually getting a Django site running on Dreamhost. Luckily, there is this <a href="http://www.soasi.com/2008/09/django-10-on-dreamhost-with-passenger-mod_rails/">blog post</a> which details exactly how to get your site up and running on Dreamhost. I have used this method a couple of times (once modified to get a Satchmo install running) and have met with success each time.</p>
<p>Once the site is running, setting up tests poses another problem. The default test behaviour for a Django site creates and then destroys a whole test database on each test run. Normally this is not a problem, but the way Dreamhost has their MySQL setup running, the commands to create and drop databases are not available outside of their administration panel. What follows is the solution I have come up with and am currently using to run Django unittests with my Dreamhost MySQL databases.</p>
<p>First of all, it is important to understand a little about the default testing setup that Django uses. When you run the command <code>python manage.py test</code>, Django looks at the TEST_RUNNER setting to determine what to do. By default this setting points to django.test.simple.run_tests. A quick look and we can see that this is the functionality we want to alter. Specifically, lines 2 and 4 shown in listing #1 are what we need to replace.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection
connection.<span style="color: black;">creation</span>.<span style="color: black;">create_test_db</span><span style="color: black;">&#40;</span>verbosity, autoclobber=<span style="color: #ff7700;font-weight:bold;">not</span> interactive<span style="color: black;">&#41;</span>
result = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TextTestRunner</span><span style="color: black;">&#40;</span>verbosity=verbosity<span style="color: black;">&#41;</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span>suite<span style="color: black;">&#41;</span>
connection.<span style="color: black;">creation</span>.<span style="color: black;">destroy_test_db</span><span style="color: black;">&#40;</span>old_name, verbosity<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h5>Listing 1: Excerpt from django.test.simple.run_tests</h5>
</p>
<p>It is these lines which make the calls to create and then drop the test database. The functionality needed, however, in order to work with Dreamhost&#8217;s setup, is to &#8220;flush&#8221; and existing test database both before and after the test run is complete. I have accomplished this through the creation of a method called <code>flush_test_db</code>, shown in Listing #2.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> flush_test_db<span style="color: black;">&#40;</span>test_db<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Method to flush out the test database, removing tables, before
    and after test runs&quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection 
    cursor = connection.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
&nbsp;
    current_tables =  connection.<span style="color: black;">introspection</span>.<span style="color: black;">table_names</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> table <span style="color: #ff7700;font-weight:bold;">in</span> current_tables:
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;use %s&quot;</span> <span style="color: #66cc66;">%</span> test_db<span style="color: black;">&#41;</span>
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;drop table %s&quot;</span> <span style="color: #66cc66;">%</span> table<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h5>Listing 2: New method to remove all tables from the test db</h5>
</p>
<p>With this method, we can drop all of the tables in the test db both before and after a test run. It is necessary to do both just in case something goes horribly awry during a test run and we end up with leftover data from a previous test run. With this new method, we can then create a new version of the run_tests method and place both methods into a new file. I called my file test_runner.py and placed it in a tests directory within my app. The complete test_runner.py is shown in Listing 3.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;Override of the simple tests module from django in order to skip
database creation and use an existing db&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> get_app, get_apps
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">backends</span>.<span style="color: black;">creation</span> <span style="color: #ff7700;font-weight:bold;">import</span> TEST_DATABASE_PREFIX
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: #dc143c;">test</span> <span style="color: #ff7700;font-weight:bold;">import</span> simple
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: #dc143c;">test</span>.<span style="color: black;">utils</span> <span style="color: #ff7700;font-weight:bold;">import</span> setup_test_environment, teardown_test_environment
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span> <span style="color: #ff7700;font-weight:bold;">import</span> management 
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> flush_test_db<span style="color: black;">&#40;</span>test_db<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Method to flush out the test database, removing tables, before
    and after test runs&quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection 
    cursor = connection.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
&nbsp;
    current_tables =  connection.<span style="color: black;">introspection</span>.<span style="color: black;">table_names</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> table <span style="color: #ff7700;font-weight:bold;">in</span> current_tables:
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;use %s&quot;</span> <span style="color: #66cc66;">%</span> test_db<span style="color: black;">&#41;</span>
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;drop table %s&quot;</span> <span style="color: #66cc66;">%</span> table<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> run_tests<span style="color: black;">&#40;</span>test_labels, verbosity=1, interactive=<span style="color: #008000;">True</span>, extra_tests=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Replacement for the run_tests in Django.
    &quot;&quot;&quot;</span>
    setup_test_environment<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    settings.<span style="color: black;">DEBUG</span> = <span style="color: #008000;">False</span>    
    suite = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestSuite</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> test_labels:
        <span style="color: #ff7700;font-weight:bold;">for</span> label <span style="color: #ff7700;font-weight:bold;">in</span> test_labels:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'.'</span> <span style="color: #ff7700;font-weight:bold;">in</span> label:
                suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_test</span><span style="color: black;">&#40;</span>label<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                app = get_app<span style="color: black;">&#40;</span>label<span style="color: black;">&#41;</span>
                suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_suite</span><span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> app <span style="color: #ff7700;font-weight:bold;">in</span> get_apps<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_suite</span><span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">test</span> <span style="color: #ff7700;font-weight:bold;">in</span> extra_tests:
        suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">test</span><span style="color: black;">&#41;</span>
&nbsp;
    old_name = settings.<span style="color: black;">DATABASE_NAME</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> settings.<span style="color: black;">TEST_DATABASE_NAME</span>:
        test_database_name = settings.<span style="color: black;">TEST_DATABASE_NAME</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        test_database_name = TEST_DATABASE_PREFIX + settings.<span style="color: black;">DATABASE_NAME</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#replace the normal DATABASE_NAME with the name of the test db</span>
    settings.<span style="color: black;">DATABASE_NAME</span> = test_database_name
&nbsp;
    <span style="color: #808080; font-style: italic;">#flush the test db</span>
    flush_test_db<span style="color: black;">&#40;</span>test_database_name<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;">#load the test db with models</span>
    management.<span style="color: black;">call_command</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'syncdb'</span><span style="color: black;">&#41;</span>
&nbsp;
    result = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TextTestRunner</span><span style="color: black;">&#40;</span>verbosity=verbosity<span style="color: black;">&#41;</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span>suite<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#flush the test db again</span>
    flush_test_db<span style="color: black;">&#40;</span>test_database_name<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#reset the value of DATABASE_NAME in settings</span>
    settings.<span style="color: black;">DATABASE_NAME</span> = old_name
    teardown_test_environment<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result.<span style="color: black;">failures</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result.<span style="color: black;">errors</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h5>Listing 3: The complete test_runner.py</h5>
</p>
<p>The final step is to point the test framework to your new test runner by placing a new line in your settings.py. The exact value will vary based on where in your project you have placed the new test runner. In this example I have placed the test_runner.py file, containing the run_tests method in the tests directory of an app called &#8216;your_app&#8217;. This is shown in listing 4.</p>
<p>
<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">TEST_RUNNER = <span style="color: #483d8b;">'your_app.tests.test_runner.run_tests'</span></pre></td></tr></table></div>

<h5>Listing 4: Settings.py setting pointing the test framework towards your new test_runner</h5>
</p>
<p>Finally a few words of caveat. I have omitted any comments I am using to tell pylint to ignore certain things and I have done little in this sample code to properly handle Exceptions that might arise. Nevertheless, this should get you a good start on running unit tests in Django if you host your site with Dreamhost.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2008/12/27/django-unittesting-on-dreamhost/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Site Changes</title>
		<link>http://www.ifisgeek.com/2008/12/21/site-changes/</link>
		<comments>http://www.ifisgeek.com/2008/12/21/site-changes/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 04:25:29 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[tags]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=115</guid>
		<description><![CDATA[Just a quick post to mention the fact that I have finally upgraded my WordPress! It&#8217;s been a long time coming and I have to say, I am impressed with how easy it was. Unfortunately, the copy I am using for this site was not installed with the DreamHost one-click-installs, so I could not do [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quick post to mention the fact that I have finally upgraded my WordPress! It&#8217;s been a long time coming and I have to say, I am impressed with how easy it was. Unfortunately, the copy I am using for this site was not installed with the DreamHost one-click-installs, so I could not do an automatic upgrade. Nonetheless, it was simple and easy. My old theme didn&#8217;t make it through the transition, however, which is the reason for the new look. I am not a big fan of this theme, but it will do until I get around to making a new one.</p>
<p>One thing that is cool about the new version of WordPress is that I now have tags on the site and on my posts. Tags. Categories. I did some reading a while back about which is better to use and the general consensus seems to be both. So I&#8217;ll have both. Yay!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2008/12/21/site-changes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Giving Back</title>
		<link>http://www.ifisgeek.com/2008/11/24/giving-back/</link>
		<comments>http://www.ifisgeek.com/2008/11/24/giving-back/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 14:32:56 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[VendAsta]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/2008/11/24/giving-back/</guid>
		<description><![CDATA[I have been a long time fan of open source software. Over the years I have utilized countless open source projects to accomplish large tasks with ease for both my day job and my consulting work. Using these projects has always saved me a lot of reinventing the wheel and has made work on projects [...]]]></description>
			<content:encoded><![CDATA[<p>I have been a long time fan of open source software. Over the years I have utilized countless open source projects to accomplish large tasks with ease for both my day job and my consulting work. Using these projects has always saved me a lot of reinventing the wheel and has made work on projects much easier.</p>
<p>For the past three and a half years, I have been working in a very heavy Microsoft shop. As a result, it was always difficult to get acceptance for open source projects at Cover-All. The more work I started doing on web projects the easier it became to bring some open source into the fold but there certainly wasn&#8217;t any interest in giving anything back to those projects we benefited from and, even if there was interest, there wouldn&#8217;t have been time to do so anyway.</p>
<p>At VendAsta, things are a lot different. Here is a company that not only embraces the use of open source projects but actually encourages everyone to give back to those projects if they make any improvements / changes to them. I absolutely love that! This has given me the opportunity to give back to my first open source project!</p>
<p>I have been doing some work on developing Facebook applications over the past few weeks. Specifically, I have been using the awesome <a href='http://code.google.com/p/pyfacebook/'>pyFacebook</a> library. This is a Python library which gives the same functionality as the Facebook-supplied PHP client library, except with the goodness of Python. A total bonus for us is the fact that the library includes functionality to work with <a href='http://code.google.com/appengine/'>Google App Engine</a>, another new technology we are using. There was a small gap in this functionality and that is where I found my opportunity. While everything was setup to work with retrieving information from Facebook in GAE (Google has disabled socket access in the version of Python available through GAE, so you need to use their urlfetch method instead of calls to httplib), the Photos.upload() method was not setup in the same manner. I needed to upload files to Facebook, so I modified the library to work the way I needed.</p>
<p>Once my mods were complete I sent them to the maintainer of the pyFacebook project and, after a few helpful suggestions from him, I had a version that he was willing to commit to the project&#8217;s svn repository: <a href='http://code.google.com/p/pyfacebook/source/detail?r=166'>http://code.google.com/p/pyfacebook/source/detail?r=166</a>. After that I was able to track down and fix an actual bug involving some infinite redirects: <a href='http://code.google.com/p/pyfacebook/source/detail?r=168'>http://code.google.com/p/pyfacebook/source/detail?r=168</a>.</p>
<p>Two very small contributions to a single project, but I am hopeful that this is only the beginning!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2008/11/24/giving-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MacHackin&#8217;</title>
		<link>http://www.ifisgeek.com/2008/11/19/machackin/</link>
		<comments>http://www.ifisgeek.com/2008/11/19/machackin/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 02:23:41 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/2008/11/19/machackin/</guid>
		<description><![CDATA[Well, I have been working and living with a MacBook Pro for a few weeks now and I have to say I&#8217;m liking it a lot more than I had thought I would. I am starting to get the hang of how everything works and I am very happy about just how similar things are [...]]]></description>
			<content:encoded><![CDATA[<p>Well, I have been working and living with a MacBook Pro for a few weeks now and I have to say I&#8217;m liking it a lot more than I had thought I would. I am starting to get the hang of how everything works and I am very happy about just how similar things are to LINUX when you open up the command line. I had heard that, despite being built on BSD, much of that functionality was crippled in some way in OSX. Thankfully, that is not the case at all.</p>
<p>I finally got a chance this week to take a crack at customizing things a little bit. I have been listening to <a href='http://www.977music.com/'>Internet Radio .977</a> lately,  a set of &#8220;radio&#8221; channels I found in my ShoutCast playlist in XBMC. One thing that is very cool about working on a Mac is that so many of the applications play really well together. For instance, if you are listening to music in iTunes, with a couple of clicks you can have the current song showing up in your status in iChat or Adium. Unfortunately for me, the .977 stream does not play in iTunes. I listen to it in VLC, which does not fit together with the chat apps the way iTunes does.</p>
<p>I did a little Googling and wasn&#8217;t able to find much on the subject. There are a few ways to get current media information out of VLC, however, most of that is geared towards playing mp3s and using these techniques I was only able to extract the name of the radio station I was listening to, not the track name that was appearing in the VLC window. Additionally, I was able to find a site that detailed writing some Applescript and BASH scripts to set iChat/Adium status to dynamically indicate your location, based on IP address. After a little tinkering I was able to put something together.</p>
<p>I won&#8217;t bother with all of the details here (anyone who wants to know how it was done, drop me a line). Basically my solution was this: setup VLC to write its log out to a file and set the verbosity of the logging to max. When the track playing changes a line is written to the log including &#8220;New Title=XXX&#8221; where XXX is the track listing as it appears in the main VLC window. This information was utilized with two BASH scripts (one to pull the last song entry from the log and parse the song from that line and another to control this whole process) and one Applescript to push the status into the chat apps. A little cron magic and it works like a charm!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ifisgeek.com/2008/11/19/machackin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
