<?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>Coyote Tracks &#187; TDD</title>
	<atom:link href="http://kagan.mactane.org/blog/tag/tdd/feed/" rel="self" type="application/rss+xml" />
	<link>http://kagan.mactane.org/blog</link>
	<description>The prints of an Internet-enabled coyote.</description>
	<lastBuildDate>Tue, 31 Jan 2012 03:26:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Testing Backward-Incompatible Changes</title>
		<link>http://kagan.mactane.org/blog/2009/10/12/testing-backward-incompatible-changes/</link>
		<comments>http://kagan.mactane.org/blog/2009/10/12/testing-backward-incompatible-changes/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 18:06:20 +0000</pubDate>
		<dc:creator>Kai MacTane</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://kai.mactane.org/blog/?p=135</guid>
		<description><![CDATA[Let&#8217;s say one day you decide to add a feature to your software or service. For example, you need a new flag on user accounts, so that different types of users get different features. (These don&#8217;t even have to be tiered account levels; maybe accounts of type &#8220;music lover&#8221; get a widget in the sidebar [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s say one day you decide to add a feature to your software or service. For example, you need a new flag on user accounts, so that different types of users get different features. (These don&#8217;t even have to be tiered account levels; maybe accounts of type &#8220;music lover&#8221; get a widget in the sidebar with suggestions for bands they might like while &#8220;sports fan&#8221; accounts get a sports scores widget instead.)</p>
<p>So, following good software development processes, you first write a couple of tests:</p>
<p><span id="more-135"></span>UserTypeOne gets features A, B, and C<br />
UserTypeOne does not get features D, E, or F<br />
UserTypeTwo does not get features A, B, or C<br />
UserTypeTwo gets features D, E, and F</p>
<p>Then you write some code that meets these tests, including creating a pair of mock users with the new flag set in both possible ways. You run the tests, and they all pass. Yay! Your new feature is ready!</p>
<p>Except that, of course, the moment you check this code in, you find that suddenly, <em>nobody can log in any more</em>. After all, the new flag is supposed to be mandatory, and that requirement is reflected in one of the changes you made to the login code. But the only users that have the NewFlag at all are the ones you just created in your fixture.</p>
<p>Sure, this will probably get caught before it goes live. Even if your entire QA department is asleep at the switch, if just one person in your organization tries to run even the most rudimentary tests, they&#8217;ll get back an error message. But &#8220;it didn&#8217;t get pushed to production&#8221; is only the most minimal level of success; I&#8217;d like to look at how <em>you</em>, the coder, could have prevented this problem. How could you keep this error from even getting checked in (and thus breaking the build and flat-lining your co-workers&#8217; productivity for a few hours)?</p>
<p>The way a real QA department would spot this problem is regression testing. But it&#8217;s not reasonable to ask every coder to do a full suite of regression tests before every commit.</p>
<p>The real failure, of course, is that you made a change that you didn&#8217;t test. But saying &#8220;force programmers to write better tests&#8221; is not a viable answer; people are imperfect. You might as well mandate &#8220;developers may not check in any code that contains bugs&#8221; as one of your organization&#8217;s rules.</p>
<p>I don&#8217;t have a good answer to this problem. Asking developers to also be QA people is completely impractical. The current solution seems to be &#8220;developers sometimes check in code which breaks the build, and blocks people&#8217;s productivity for a while&#8221;. (Distributed SCM can help mitigate this.)</p>
<p>Is there something QA people know that developers don&#8217;t, that would make an easy solution that we could adopt?</p>
]]></content:encoded>
			<wfw:commentRss>http://kagan.mactane.org/blog/2009/10/12/testing-backward-incompatible-changes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes on LJ Content Sieve</title>
		<link>http://kagan.mactane.org/blog/2009/07/04/notes-on-lj-content-sieve/</link>
		<comments>http://kagan.mactane.org/blog/2009/07/04/notes-on-lj-content-sieve/#comments</comments>
		<pubDate>Sat, 04 Jul 2009 21:07:42 +0000</pubDate>
		<dc:creator>Kai MacTane</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[my projects]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://kai.mactane.org/blog/?p=78</guid>
		<description><![CDATA[My latest project is something I call &#8220;LJ Content Sieve&#8221;: a Greasemonkey script to filter out content on one&#8217;s Livejournal views based on nearly any attribute of a post or comment. However, Livejournal is very customizable. It has 31 different &#8220;layouts&#8221;, each of which can then be further &#8220;themed&#8221; by application of CSS. This means [...]]]></description>
			<content:encoded><![CDATA[<p>My latest project is something I call &#8220;LJ Content Sieve&#8221;: a Greasemonkey script to filter out content on one&#8217;s Livejournal views based on nearly any attribute of a post or comment.</p>
<p>However, Livejournal is very customizable. It has 31 different &#8220;layouts&#8221;, each of which can then be further &#8220;themed&#8221; by application of CSS. This means that a user viewing a given journal, community, or single post, at a given time, may receive an HTML document containing any of 31 different DOM structures.</p>
<p>This means that finding a post&#8217;s author, or title, or even just a single post or comment, is not a straightforward process. I&#8217;ve set myself up a Ruby script that downloaded my &#8220;friends&#8221; view, a representative entry with lots of comments, and my own journal view, thus giving me a set of 93 fixtures that I can test against. The Ruby script also tweaked each fixture in the process of spooling it to my hard drive, by adding the proper calls to JSUnit files.</p>
<p>At the end of each document&#8217;s &lt;head&gt; element, there&#8217;s a call to <code>jsUnitCore.js</code>. Then, at the end of each &lt;body&gt;, I add a call to the <code>lj-content-sieve.user.js</code> script itself, as well as a set of test files that depends on which fixture this is. Every fixture gets an <code>ljcs-global-tests.js</code> call added to it&nbsp;&mdash; that file contains tests that should work anywhere, regardless of what sort of page you&#8217;re on.</p>
<p>Then all the &#8220;friends&#8221; page fixtures get an <code>ljcs-friends-tests.js</code> file, which tests operations that should happen on every friends page. For example, determining which entries need to be deleted. (In contrast, single-entry pages get <code>ljcs-entry-tests.js</code>, and the page from my own journal&nbsp;&mdash; which stands in for a view of a community&nbsp;&mdash; gets <code>ljcs-self-tests.js</code>.)</p>
<p>Finally, each fixture page gets a test file based on its layout: the &#8220;3 Column&#8221; layout gets <code>ljcs-3&nbsp;Column-tests.js</code>, while &#8220;Cuteness Attack&#8221; gets <code>ljcs-Cuteness&nbsp;Attack-tests.js</code>. (Hey, I didn&#8217;t write or name the layouts; I just have to make sure LJCS works with all of &#8216;em.) These files will test that the actual DOM manipulations work properly.</p>
<p>Without test-driven development and automated testing to ensure that each layout and page-type is being handled properly, I don&#8217;t think this project would be manageable at all.</p>
]]></content:encoded>
			<wfw:commentRss>http://kagan.mactane.org/blog/2009/07/04/notes-on-lj-content-sieve/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>TDD and Peace of Mind</title>
		<link>http://kagan.mactane.org/blog/2009/05/04/tdd-and-peace-of-mind/</link>
		<comments>http://kagan.mactane.org/blog/2009/05/04/tdd-and-peace-of-mind/#comments</comments>
		<pubDate>Mon, 04 May 2009 16:53:10 +0000</pubDate>
		<dc:creator>Kai MacTane</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[my projects]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://kai.mactane.org/blog/2009/05/04/tdd-and-peace-of-mind/</guid>
		<description><![CDATA[Let&#8217;s face it, we&#8217;re not perfect. As much as I might realize that automated testing is a good practice, it still feels like a chore sometimes. In my latest round of personal-project development, just setting up a decent set of test fixtures and a working test framework turned into something of a hassle, as it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s face it, we&#8217;re not perfect. As much as I might realize that automated testing is a good practice, it still <em>feels</em> like a chore sometimes. In my latest round of personal-project development, just setting up a decent set of test fixtures and a working test framework turned into something of a hassle, as it&#8217;s my first attempt both at Greasemonkey scripting <em>and</em> at building a script that will act on Livejournal pages. (Since LJ users can customize their views with any of 36 basic &#8220;styles&#8221;, this means quite a few fixtures.)</p>
<p>So it was awfully tempting to say &#8220;screw this!&#8221; and just start writing code&nbsp;&mdash; you know, &#8220;code that works, code that gets stuff done&#8221;. Actual <em>program logic</em>, instead of testing tools. &#8220;Why don&#8217;t I just get something built to begin with,&#8221; I asked myself, &#8220;and then I can try to test that?&#8221;</p>
<p>Ha, ha. Of course, we all know that starting off without any tests just makes it easier to continue without them later. So I took the virtuous road, forced myself to get tests working, but allowed myself to skimp by only setting up fixtures for 3 of the 36 styles. The other styles are something I will <em>have to</em> go back and fill in before I can release, so there&#8217;s no chance I&#8217;ll &#8220;give myself permission&#8221; to blow them off.</p>
<p>When you really want to be writing code (because let&#8217;s face it, you consider yourself a coder, not a tester), it&#8217;s pretty annoying to write tests instead. But writing tests is at least a form of writing; if you&#8217;re not even writing tests, but rather setting up a test framework and fixtures, that&#8217;s almost excruciating.</p>
<p>But it all became worth it the moment I made a change in one of my basic data structures. I had a structure (what a Perlist would call a hash of arrays) that held information about how to identify which LJ style the page uses. Then I realized I didn&#8217;t want to have a separate structure for how to manipulate the page; instead, all information about LJ&#8217;s styles and DOM structure should live in one place.</p>
<p>So I altered the structure, then altered the functions created so far that rely on it. And that&#8217;s where I would then have to wonder, &#8220;How badly did I break everything?&#8221; Instead, I just ran my JSunit tests again. And seeing them pass was instant peace of mind. I don&#8217;t have to worry that there&#8217;s some hidden flaw waiting there, ready to be exposed by a user doing something unexpected. And as I add the other styles, I can easily be sure my code works for them, as well.</p>
<p>I&#8217;m still fairly early in the development of this code, and while unit testing has cost me a bit of time, it&#8217;s given me back <em>peace of mind</em>. The time profit? I have no doubt that will come later. (And had I made any errors in my data-structure change, the unit tests would have helped me find them more quickly than the usual debugging methods.)</p>
]]></content:encoded>
			<wfw:commentRss>http://kagan.mactane.org/blog/2009/05/04/tdd-and-peace-of-mind/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>I&#8217;m Getting Tired of Yak-Shaving</title>
		<link>http://kagan.mactane.org/blog/2008/12/18/im-getting-tired-of-yak-shaving/</link>
		<comments>http://kagan.mactane.org/blog/2008/12/18/im-getting-tired-of-yak-shaving/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 03:59:42 +0000</pubDate>
		<dc:creator>Kai MacTane</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[diary]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://kai.mactane.org/blog/?p=11</guid>
		<description><![CDATA[It seems like every time I try to get around to actually writing some code, I discover yet another thing that I have to do in order to make that more possible. Today, it was: Get PHPUnit installed on L&#243;rien, so I could run my unit tests locally during development, rather than having to shove [...]]]></description>
			<content:encoded><![CDATA[<p>It seems like every time I try to get around to actually <em>writing some code</em>, I discover yet another thing that I have to do in order to make that more possible. Today, it was: Get PHPUnit installed on <span style="cursor: help; border-bottom: 1px dotted;" title="my Windows workstation">L&oacute;rien</span>, so I could run my unit tests locally during development, rather than having to shove everything back up to <span style="cursor: help; border-bottom: 1px dotted;" title="my Linux server, where I used to do such development">Finrod </span>every time I wanted to run a single test.</p>
<p>The <a href="http://en.wiktionary.org/wiki/yak_shaving">yak-shaving</a> odyssey that this necessitated involved upgrading my local copy of PHP (which originally came with InstantRails) from 4.whatever to 5.2.8, so that I could develop PHP5 code at all, then installing PEAR so that I could use it to get PHPUnit, and also resolving the weird extension-loading bugs on PHP for Windows (for example, you have to load <code>php_mbstring.dll</code> <em>before</em> <code>php_exif.dll</code>, or else both of them will fail and complain. Ditto with <code>php_pdo.dll</code> and <code>php_sqlite.dll</code>. None of this is documented in the manual; you have to Google on it and get links to the bug database. Joy.)</p>
<p>But I can now run PHPUnit test on the stuff that I&#8217;m working on, <em>locally</em> rather than remotely. So&#8230; <em>now</em> can I get some code written?</p>
]]></content:encoded>
			<wfw:commentRss>http://kagan.mactane.org/blog/2008/12/18/im-getting-tired-of-yak-shaving/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

