<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Adam Goucher</title>
	
	<link>http://adam.goucher.ca</link>
	<description>Quality through Innovation</description>
	<pubDate>Tue, 07 Oct 2008 13:22:29 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.1</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/AdamGoucher" type="application/rss+xml" /><item>
		<title>Multiple Secure Virtual Hosts with Apache</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/413800596/</link>
		<comments>http://adam.goucher.ca/?p=485#comments</comments>
		<pubDate>Tue, 07 Oct 2008 13:22:29 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=485</guid>
		<description><![CDATA[We&#8217;re breaking our monolithic application into a series of smaller services that a much lighter-weight Rails application will then utilize. These services will be (initially) sitting on the same machine behind an apache load balancer. The front application will be talking SSL to the load balancer. This post is essentially how to wire this all [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re breaking our <a href="http://www.zerofootprint.net/calculators">monolithic application</a> into a series of smaller services that a much lighter-weight Rails application will then utilize. These services will be (initially) sitting on the same machine behind an apache load balancer. The front application will be talking SSL to the load balancer. This post is essentially how to wire this all together (so it can be tested in a configuration similar to production)<br />
<br />
Before starting, here are the assumptions I am going to be working from:</p>
<ul>
<li>The front application is currently able to talk directly to each of the services directly (no proxy or clustering)</li>
<li>Rails is being served by mongrel. Sorry Monorail or Passenger kids; you are too bleeding edge for me</li>
<li>This was written on a mac so some of the security conventions (like sudo for lots of stuff) might be OS quirks</li>
</ul>
<p>
<b>Part 1: Generate SSL Certificates</b><br />
<br />
In production, any customer port that is secured should likely be done through a commercial Certificate Authority (CA) as they have their Root Certificates installed in browsers by default (a perk they pay dearly for). But given that this is being done in the context of testing <i>and</i> the services will only only be used by clients of our creation we can use a pretend CA. The one that is in the copy of <a href="http://www.openssl.org">OpenSSL</a> that is on this machine is called demoCA. Let&#8217;s set it up.<br />
</p>
<pre class="code">Setup your CA
$ mkdir ~/certificates
$ cd ~/certificates
$ mkdir demoCA
$ mkdir demoCA/certs
$ echo 00 > demoCA/serial
$ touch demoCA/index.txt</pre>
<p>
Now that you have a bit of infrastructure taken care of, you need to make the CA&#8217;s key<br />
</p>
<pre class="code">$ openssl genrsa -des3 -out ca.key 1024</pre>
<p>
Then create a new request and sign it with the key in one shot<br />
</p>
<pre class="code">$ openssl req -new -x509 -days 365 -key ca.key -out ca.crt</pre>
<p>
Now that we have a CA you can make the request for your service. But first it needs a key too.<br />
</p>
<pre class="code">$ openssl genrsa -out s1.key 1024</pre>
<p>
(alternatively you could have added a -des3 to password protect the key, but it is a pain. don&#8217;t do it)<br />
<br />
Here is the actual request. It is <i>very</i> important that when it prompts you for the &#8216;Common Name&#8217; (CN) that you put in the host name of the machine you are trying to access. For instance, adam.zerofootprint.net. Crypto is all about trust and one of the checks is that the hostname matches the cn.<br />
</p>
<pre class="code">$ openssl req -new -key s1.key -out s1.csr</pre>
<p>
And sign it using our CA<br />
</p>
<pre class="code">$ openssl ca -in s1.csr -out s1.pem -keyfile ca.key -cert ca.crt</pre>
<p>
If you put a password on your server&#8217;s keyfile, you should remove it. It&#8217;s not necessarily as secure anymore, but&#8230;<br />
</p>
<pre class="code">$ cp s1.key s1.key.orig
$ openssl rsa -in s1.key.orig -out s1.key</pre>
<p>
Repeat the creation of certificates for the amount of services you have making sure to change the name of the files things are saved into.<br />
<br />
<b>Part 2: Setup Virtual Servers</b><br />
I really don&#8217;t like how Apache is configured on the Mac by default, so this next section will likely be redundant to Ubuntu or other nicely configured servers.<br />
<br />
Everything in Apache for the last couple years has been setup as a Virtual Server. Even the default port (80) is setup in that manner. We&#8217;re going to pretend that there are 2 services going to be hosted in this setup. Infrastructure again.<br />
</p>
<pre class="code">$ cd /etc/apache2
$ sudo mkdir sites-available
$ sudo mkdir sites-enabed
$ cd sites-available</pre>
<p>
In the <i>sites-available</i> directory you put in the actual virtual host definitions. Here is the virtual host definition I started with for one of the services. I also have one for port 7501.<br />
</p>
<pre class="code">Listen 7500
NameVirtualHost *:7500

&lt;VirtualHost *:7500&gt;
DocumentRoot "/Library/WebServer/Documents/s1"
# you need a different ServerName for each host
ServerName s1.your.site
ServerAdmin you@example.com
ErrorLog "/private/var/log/apache2/s1-ssl-error.log"

&lt;/VirtualHost&gt;</pre>
<p>
In order to have apache pick up these hosts you need to include them in your main config file. On the mac it is httpd.conf.<br />
</p>
<pre class="code">Include /etc/apache2/sites-enabled/*</pre>
<p>
This of course won&#8217;t work without a bit of magic. I&#8217;m only showing the first service, but you have to do this for each one.<br />
</p>
<pre class="code">$ cd /etc/apache/sites-enabled
$ ln -s ../sites-enabled/s1 s1</pre>
<p>
Restart apache and make sure that you can get to all your virtual hosts. They are still running in the clear over http.<br />
<br />
<b>Part 3: SSL-ize Virtual Servers</b><br />
The end goal of course is have communications to these virtual servers to be secured so now we actually turn it on. Again, some infrastructure.<br />
</p>
<pre class="code">$ cd /etc/apache2
$ sudo mkdir certificates
$ sudo cp ~/certificates/s1.key .
$ sudo cp ~/certificates/s1.pem .</pre>
<p>
Repeat for each of your service keys that you made in Part 1.<br />
<br />
Now modify your virtual hosts</p>
<pre class="code">Listen 7500
NameVirtualHost *:7500

&lt;VirtualHost *:7500&gt;
DocumentRoot "/Library/WebServer/Documents/s1"
# you need a different ServerName for each host
ServerName s1.your.site
ServerAdmin you@example.com
ErrorLog "/private/var/log/apache2/s1-ssl-error.log"

# these were all the defaults from the stock mac install; tune as necessary/desired
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile "/private/etc/apache2/certificates/s1.pem"
SSLCertificateKeyFile "/private/etc/apache2/certificates/s1.key"

BrowserMatch ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog "/private/var/log/apache2/ssl_request_log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

&lt;/VirtualHost&gt;</pre>
<p>
Again, restart apache and see that going to your ports over https works and you have the correct certificate being served (view the certificate and check the CN)<br />
<br />
<b>Part 4: Contacting the Nodes</b><br />
I&#8217;m going to skip how you setup a mongrel cluster as there are a tonne of sites that deal with that already. In this example I&#8217;m going to have a 2 node cluster.<br />
<br />
We&#8217;re going to use the same convention for the cluster nodes as we used for the virtual hosts.<br />
</p>
<pre class="code">$ cd /etc/apache2
$ sudo mkdir nodes-available
$ sudo mkdir nodes-enabled
$ cd nodes-available</pre>
<p>
In the nodes-available you want to define the members of each node. Each of our services is going to have only 1 node in this example. And each member is going to listen on localhost.<br />
</p>
<pre class="code">BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001</pre>
<p>
Now you might be a bit alarmed that it is using http which is somewhat ironic given the whole point of this is to be more secure, but if someone has the ability to sniff localhost then you are screwed already. Naturally, each member needs to have its own ports and that the ports are correct.<br />
<br />
In order to redirect clients around to the various nodes we need to do a bit of modification to our virtual hosts file we created in step 2 and added ssl stuff to in 3. Specifically the Proxy section and the rewrite rules.<br />
</p>
<pre class="code">Listen 7500
NameVirtualHost *:7500

&lt;Proxy balancer://s1_cluster&gt;
  Include "/etc/apache2/nodes-enabled/s1*"
&lt;/Proxy&gt;

&lt;VirtualHost *:7500&gt;
  # various SSL settings including certificates for this port go here

  RewriteEngine On
  RewriteRule ^/(.*)$ balancer://s1_cluster%{REQUEST_URI} [P,QSA,L]
&lt;/VirtualHost&gt;</pre>
<p>
That&#8217;s all there is to it. Now you will be able to run multiple services on the same host with proper ssl certificates. Once a service has outgrown its ability to share space with the other services you can just move the certificate to a separate machine and tweak the dns to point to the new location (since the CN is the machine <i>name</i>). No service reconfiguration necessary.<br />
<br />
Hope this saves someone some thinking.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=485</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=485</feedburner:origLink></item>
		<item>
		<title>Types of Exploratory Testing</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/410218061/</link>
		<comments>http://adam.goucher.ca/?p=479#comments</comments>
		<pubDate>Fri, 03 Oct 2008 12:41:18 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=479</guid>
		<description><![CDATA[At CAST 2008, part of my talk was on using skill progression charts to help testers grow just as how (lacrosse) coaches do. At the same time I was saying that I don&#8217;t think people new to testing should be given free hand to do exploratory testing as they do not have the library of [...]]]></description>
			<content:encoded><![CDATA[<p>At <a href="http://www.associationforsoftwaretesting.org/drupal/cast2008">CAST 2008</a>, part of my talk was on using skill progression charts to help testers grow just as how (lacrosse) coaches do. At the same time I was saying that I don&#8217;t think people new to testing should be given free hand to do exploratory testing as they do not have the library of tricks and problems to draw from.<br />
<br />
<a href="http://blogs.msdn.com/james_whittaker/">James Whittaker</a> ends his Prevention v. Cure series (<a href="http://blogs.msdn.com/james_whittaker/archive/2008/07/24/prevention-v-cure-part-1.aspx">Part 1</a>, <a href="http://blogs.msdn.com/james_whittaker/archive/2008/07/24/prevention-v-cure-part-2.aspx">Part 3</a>, <a href="http://blogs.msdn.com/james_whittaker/archive/2008/07/24/prevention-v-cure-part-3.aspx">Part 3</a>, <a href="http://blogs.msdn.com/james_whittaker/archive/2008/07/24/prevention-v-cure-part-4.aspx">Part 4</a>, <a href="http://blogs.msdn.com/james_whittaker/archive/2008/07/24/prevention-v-cure-part-5.aspx">Part 5</a>) shares how Microsoft categorizes Exploratory testing which both confirms and makes me question the second point.<br />
</p>
<ul>
<li><i>Freestyle Exploratory Testing</i> - This is where new testers start at, and as James points out &#8220;it’s far more ‘exploratory’ than it is ‘testing’ so expectations should be set accordingly.&#8221; Yes, there is value from learning the system, but there is no reason why the learning and testing cannot be done accordingly. I suspect most experienced testers are incapable of doing Freestyle testing. They might claim they are, but they are applying a series of internal heuristics to the activity.</li>
<li><i>Scenario-based Exploratory Testing</i> - If you are smart, this is where you try to start new testers at. This is a hybrid of the classical scripted testing and SBTM or as James says &#8220;involves a starting point of user stories or documented end-to-end scenarios that we expect our ultimate end user to perform.&#8221; The person doing the tester doesn&#8217;t need to have all the &#8216;l33t testing skillz&#8217; to design the scenarios, but are encouraged to be brain-engaged with their testing.</li>
<li><i>Strategy-based Exploratory Testing</i> - Strategy-based testing is the holy grail of exploratory testing where &#8220;the better the repertoire of testing knowledge, the more effective the testing.&#8221; Notice the <i>better the repertoire</i> aspect of this. It was this point that I was trying to make at CAST as new testers are not going to have the repertoire built-up. Testers with a couple years experience have started build up their own internal metrics and heuristics to apply to a testing problem that new testers just plain cannot have. The kicker is of course that these are continually involving.</li>
<li><i>Feedback-based Exploratory Testing</i> - This feels like a sub category of Scenario-based Exploratory Testing. You are doing exploratory testing, but rather than executing against a user strategy you execute against some form of feedback. James&#8217; example is code coverage.</li>
</li>
<p>
Of these 4 buckets, I think the middle 2 are the most valuable. Stategy-based is where you will want to end up if you are going to continue having fun testing software. In the meantime, Scenario-based will help hone you instincts to get there.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=479</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=479</feedburner:origLink></item>
		<item>
		<title>5 more 5 questions with…</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/406669187/</link>
		<comments>http://adam.goucher.ca/?p=478#comments</comments>
		<pubDate>Mon, 29 Sep 2008 22:28:35 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Quality]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=478</guid>
		<description><![CDATA[I&#8217;ve been neglecting my 5 questions with&#8230; folder recently. Here is the catch-up; with commentary. Of course.

Amol Kher

Models are what developers will hate to love or love to hate - Or both?


Ethan John

I had no idea that [testing] was something I could do for a living. - This is such an important problem for the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been neglecting my <a href="http://www.ddj.com/blog/debugblog/archives/2006/09/five_questions.html">5 questions with&#8230;</a> folder recently. Here is the catch-up; with commentary. Of course.<br />
<br />
<a href="http://www.ddj.com/blog/debugblog/archives/2008/08/five_questions_62.html">Amol Kher</a></p>
<ul>
<li>Models are what developers will hate to love or love to hate - <i>Or both?</i></li>
</ul>
<p>
<a href="http://www.ddj.com/blog/debugblog/archives/2008/08/five_questions_63.html">Ethan John</a></p>
<ul>
<li>I had no idea that [testing] was something I could do for a living. - <i>This is such an important problem for the testing community. One which I have no idea how to fix.</i></li>
</ul>
<p>
<a href="http://www.ddj.com/blog/debugblog/archives/2008/08/five_questions_64.html">Michael Corning</a></p>
<ul>
<li>The first thing a tester needs to know about testing is that you cannot test what you do not understand - <i>Oh I so don&#8217;t agree. Maybe if you tacked on a &#8216;or does not want to understand&#8217; I could go along with the statement. As it is now it is equivalent to saying that all programmers need to know Assembly. Heck, a lot of programmers nowadays don&#8217;t even know C and the &#8216;joy&#8217; that is pointers and manual memory management.</i></li>
<li>In my mind, the tester is an auditor. The function of the auditor is to attest. In financial auditing, the auditor attests with his or her signature that the financial results fairly represent the financial results of business operations. From this attestation, other decision makers make their decisions. Both the auditor and the tester provide information to the eco-system. - <i>Attestation implies a certain level of guarantee. Again, to cite the <a href="http://www.testingeducation.org/k04/documents/BBSTOverviewPartC.ppt">diagram in the BBST Foundations material</a>, there are so many factors that attesting to the quality is a trap &#8212; at best. An opinion, sure. But attestation? Nope.</i></li>
<li>I do my best to use the machine to generate test cases for me. - <i>All hail the machine. This to me is the point you want to evolve your automation towards</i></li>
</ul>
<p>
<a href="http://www.ddj.com/blog/debugblog/archives/2008/09/five_questions_65.html">Keith Braithwaite</a></p>
<ul>
<li>Write tests to capture requirements. Count tests written to measure scope. Count tests passing to measure delivery. Use tests to drive design. Use tests to communicate between teams, with customers. Use tests to meet regulatory loads and show compliance without mountains of paper. Oh, and to find defects too. But that last one is just the cherry on the cake. - <i>Count tests to get a useless number; I can write a million tests that provide useless information but still shows 7 figures in the count. Use tests to confuse the customer; maybe he deals with different people in different organizations, but the people on conference calls I have been on would go glassy-eyed in under a minute if presented with tests. Which isn&#8217;t bad as they don&#8217;t need to know how to read the tests. This applies too to requirements. I&#8217;m in this situation now, and it is not enjoyable in the least. Capture the requirements in a document, or series of documents and make sure they evolve with the application. Or better still, put them in a wiki.</i></li>
</ul>
<p></p>
<ul>
<li><a href="http://www.ddj.com/blog/debugblog/archives/2008/09/five_questions_66.html">Gil Broza</a>
<ul>
<li>Think-once-then-automate</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=478</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=478</feedburner:origLink></item>
		<item>
		<title>The Identifiable Victim</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/405806634/</link>
		<comments>http://adam.goucher.ca/?p=477#comments</comments>
		<pubDate>Mon, 29 Sep 2008 01:02:42 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Quality]]></category>

		<category><![CDATA[marketing]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=477</guid>
		<description><![CDATA[Once again thanks to Dan Ariely&#8217; blog we have the concept of &#8216;the identifiable victim effect&#8217; (which amazingly doesn&#8217;t seem to have a wikipedia entry). He describes this as the effect of one individual, identifiable, victim who is known in full detail can evoke a much deeper feelings, emotions and sympathy than a large group [...]]]></description>
			<content:encoded><![CDATA[<p>Once again thanks to <a href="http://www.predictablyirrational.com/?p=297">Dan Ariely&#8217; blog</a> we have the concept of &#8216;the identifiable victim effect&#8217; (which amazingly doesn&#8217;t seem to have a wikipedia entry). He describes this as <i>the effect of one individual, identifiable, victim who is known in full detail can evoke a much deeper feelings, emotions and sympathy than a large group of anonymous individuals</i>.<br />
<br />
This has potentially huge ramifications for when we write bug reports. I&#8217;ve been saying for awhile that a large part of what we do is marketing (and thus the increase of marketing-esque posts). And I&#8217;m not alone on this. The slides for the BBST Bug Advocacy section includes a section on &#8216;motivating the bug fix&#8217;. Here is a line from slide 21 of the course notes:<br />
<br />
<i>You may or may not have found the best example of a failure that can be caused by the underlying fault.</i><br />
<br />
I&#8217;m pretty sure in this case they mean example to be &#8216;a reproducible thing you could call a bug&#8217;, but example could also be read as &#8216;a story which conveys the nature or intent of the bug report&#8217;. In other words, have you started writing a report which is written in very fuzzy, vague ways or one that is specific to a person (or an identifiable group of persons)?<br />
<br />
More on the identifiable victim effect can be found in:</p>
<ul>
<li><a href="http://idei.fr/doc/conf/psy/papers/small.pdf">Running Head: Learning about the Identifiable Victim Effect</a> by Deborah A. Small, George Loewenstein and Paul Slovic</li>
<li><a href="http://www.ssireview.org/articles/entry/crisis_mentality/">Crisis Mentality - Why sudden emergencies attract more funds than do chronic conditions, and how nonprofits can change that</a> by Keith Epstein</li>
</ul>
<p>(both are big articles and I didn&#8217;t actually read them, but they were referenced a couple times when looking up the topic)</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=477</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=477</feedburner:origLink></item>
		<item>
		<title>There is a lot to think about doing execution replays</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/404677910/</link>
		<comments>http://adam.goucher.ca/?p=476#comments</comments>
		<pubDate>Sat, 27 Sep 2008 14:01:27 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Quality]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=476</guid>
		<description><![CDATA[I first became aware of the guys behind Power of 2 Games from a post one of them made comparing the speed of various c++ compilers; speed being important in the feedback loop that CI provides you. Their blog is pretty low volume and is generally aimed at the c++ and game worlds but is [...]]]></description>
			<content:encoded><![CDATA[<p>I first became aware of the guys behind <a href="http://powerof2games.com">Power of 2 Games</a> from a post one of them made <a href="http://www.gamesfromwithin.com/articles/0509/000100.html">comparing the speed of various c++ compilers</a>; speed being important in the feedback loop that CI provides you. Their blog is pretty low volume and is generally aimed at the c++ and game worlds but is generally pretty high quality when they get around to making a post.<br />
<br />
One of them from this month was a reprint from a game industry magazine in which they talk about using a playback system to aid in their testing. The <a href="http://powerof2games.com/node/36">second part of the article</a> deals mainly with the problems that can trip up your playback system and I think apply even to those who are not using playback techniques for games. Here are the choice bits (with my commentary):</p>
<ul>
<li>Middleware libraries will often have slightly different behaviors in debug and release mode - <i>Lower environments almost always run with debug symbols, etc. installed. Production rarely does. Think about how, where and why your scripts will be run before trying to get value from them.</i></li>
<li>As a general rule, treat debug and release builds as if they were different versions</li>
<li>Cranking up the compiler warning level to the maximum will allow it to catch some of the most obvious cases of reading uninitialized variables. For extra checks, I recommend a static code analysis program such as PC Lint. That&#8217;s almost guaranteed to catch every use of uninitialized variables (along with ten thousand other things, some of them extremely useful, though most of them you probably won&#8217;t care about at all). - <i>Be sure to spend the time to tune what the tool checks for to get rid of the ten thousand things fast or people will ignore the list quickly</i></li>
<li>&#8230;  it&#8217;s considered a good practice to avoid using pointer values for anything other than dereferencing them and accessing the data they&#8217;re pointing to</li>
<li>Data received from the network most definitely influences the game itself, so it&#8217;s another input to the game. - <i>I am reminded of a graphic in the BBST course (<a href="http://www.testingeducation.org/k04/documents/BBSTOverviewPartC.ppt">slide 17</a>) which can be attributed back to Doug Hoffman.</i></li>
<li><a href="http://www.replaysolutions.com/technology">ReplayDIRECTOR</a> - <i>appears to be a record/playback tool on some serious steroids</i></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=476</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=476</feedburner:origLink></item>
		<item>
		<title>Ideology vs. Facts</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/403729006/</link>
		<comments>http://adam.goucher.ca/?p=475#comments</comments>
		<pubDate>Fri, 26 Sep 2008 12:18:46 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=475</guid>
		<description><![CDATA[Here are a bunch of quotes from articles originally found via slashdot claiming &#8216;Studies Say Ideology Trumps Facts&#8217;. I think they go a long way in explaining the various political battles that go on in the testing world and how people seem to argue themselves into a corner in the face of (what appears to [...]]]></description>
			<content:encoded><![CDATA[<p>Here are a bunch of quotes from articles originally found via <a href=" http://science.slashdot.org/article.pl?sid=08/09/25/036232&#038;from=rss">slashdot</a> claiming &#8216;Studies Say Ideology Trumps Facts&#8217;. I think they go a long way in explaining the various political battles that go on in the testing world and how people seem to argue themselves into a corner in the face of (what appears to be) overwhelming facts to the contrary. Likely also explains the eternal optimism of product management in the face of a major bug backlog, etc..<br />
<br />
<a href="http://arstechnica.com/news.ars/post/20080924-does-ideology-trump-facts-studies-say-it-often-does.html">ars technica</a><br />
</p>
<ul>
<li>Cognitive dissonance won&#8217;t help people make rational decisions, but it also suggests that there&#8217;s little point in arguing with someone who holds an opposing belief.</li>
<li>The research might also apply beyond the political to other attitudes—I&#8217;m thinking of the constant flame wars between fans of the PS3 and Xbox 360, or Mac and PC users.</li>
<li>It seems to suggest that this effect might lead to problems when it comes to efforts to educate people about controversial or politically charged topics</li>
</ul>
<p>
<a href="http://www.washingtonpost.com/wp-dyn/content/article/2008/09/14/AR2008091402375.html?nav=emailpage">Washington Post</a><br />
</p>
<ul>
<li>&#8230; misinformation can exercise a ghostly influence on people&#8217;s minds after it has been debunked &#8212; even among people who recognize it as misinformation. In some cases, correcting misinformation serves to increase the power of bad information.</li>
<li>&#8220;backfire effect&#8221;</li>
<li>Upon hearing a refutation, &#8230; might &#8220;argue back&#8221; against the refutation in their minds, thereby strengthening their belief in the misinformation.</li>
</ul>
<p><a href="http://www.onthemedia.org/transcripts/2008/09/19/03">On The Media</a><br />
</p>
<ul>
<li>&#8230; when people are predisposed to buy a piece of bad information, the refutation ends up essentially not correcting the misinformation entirely. It corrects it only part way, leaving residual feelings of negativity toward whoever the target of the misinformation was.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=475</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=475</feedburner:origLink></item>
		<item>
		<title>Stickiness</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/402764512/</link>
		<comments>http://adam.goucher.ca/?p=474#comments</comments>
		<pubDate>Thu, 25 Sep 2008 12:40:30 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Quality]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=474</guid>
		<description><![CDATA[I get a copy of Business Week from my father-in-law after he is done with it. The back page of each issue is by Jack and Suzy Welch where they answer a reader&#8217;s question. This week&#8217;s was what big business imperative doesn&#8217;t get enough attention. Their answer was stickiness.


Quality doesn&#8217;t get talk about as much [...]]]></description>
			<content:encoded><![CDATA[<p>I get a copy of <a href="http://www.businessweek.com">Business Week</a> from my father-in-law after he is done with it. The back page of each issue is by Jack and Suzy Welch where they answer a reader&#8217;s question. This week&#8217;s was <i>what big business imperative doesn&#8217;t get enough attention</i>. Their answer was stickiness.<br />
</p>
<ul>
<li>Quality doesn&#8217;t get talk about as much as it used to, but that&#8217;s because it is a given.</li>
<li>What is surprising, however, is how exceptional and inventive customer service needs to be to stand out these days</li>
<li>&#8230; but another approach to stickiness can pack an even bigger wallop. It requires moving &#8230; to a product-and-long-term-service-business by guaranteeing productivity gains to customers</li>
<li>Almost all companies can create stickiness by sharing knowhow.</li>
<li>&#8230; unbridled sharing of expertise creates a real affinity &#8230;</li>
<li>&#8230; many businesses can create stickiness by building user communities. Every year &#8230; hosts conferences. These aren&#8217;t sales events per se, but you can be sure that attendees leave with a feeling of partnership &#8230;</li>
<li>Organizers must come to see the world through customers&#8217; eyes</li>
</ul>
<p>
The first point is a biggie. Now they were talking about manufacturing (I think) but it applies to software as well. Especially when there are viable competitors in the space. Quality <i>should</i> be a given.<br />
<br />
The other points are also interesting from a larger, more strategic perspective. How can you share expertise and knowhow? Open up your bug tracker. Or have someone from the QA or test groups contribute to the corporate blog about how they work to protect the customer&#8217;s interests.<br />
<br />
Which leads to the last point. Running out of ideas to test with? Stop looking at the application with all your insider knowledge. Look at it instead as a user would, without all the tricks and secret switches you have picked up along the way.<br />
<br />
Here is a <a href="http://www.welchway.com/Management/Strategy/Making-Strategy/The-Importance-of-Being-Sticky.aspx">link to the full article</a> to read it in the proper context.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=474</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=474</feedburner:origLink></item>
		<item>
		<title>Controlling Apache nodes</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/401889630/</link>
		<comments>http://adam.goucher.ca/?p=473#comments</comments>
		<pubDate>Wed, 24 Sep 2008 15:25:46 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=473</guid>
		<description><![CDATA[We have the pretty standard server configuration of a load balancer (apache) in front of two machines which serve the actual content. Through the process of trying to upgrade a machine I realized they were not configured to easily bring up or down on their own. In commercial production (Websphere and WebLogic for instance) you [...]]]></description>
			<content:encoded><![CDATA[<p>We have the pretty standard server configuration of a load balancer (apache) in front of two machines which serve the actual content. Through the process of trying to upgrade a machine I realized they were not configured to easily bring up or down on their own. In commercial production (Websphere and WebLogic for instance) you just go to the admin console and take a node out of the pool. Not so with our rig. Here is the solution I came up with. I think it is pretty elegant (though I am sure it is just reinventing the wheel).<br />
</p>
<ol>
<li>Directory structure - I created 2 directories in the apache config directory (/etc/apache2 in this case): nodes-available and nodes-enabled</li>
<li>Creating the nodes - We had all our load balanced ports in a single file. Those got broken in to separate files depending on which machine they were on. (Lets call them zfp1 and zfp2 for this example.) These files get placed in the nodes-available directory.<br />
</p>
<pre class="code">$ cat nodes-available/zfp1
BalancerMember http://x.y.z.a:8000
...
BalancerMember http://x.y.z.a:8019</pre>
</li>
<li>Enabling the nodes - The nodes are at this point both disabled which is not really an ideal situation. To enable them we create a symlink from the nodes-enabled directory into the nodes-available one for each node. For example, nodes-enabled/zfp1 links to nodes-available/zfp1.<br />
</p>
<pre class="code">$ ls -l nodes-enabled/
total 0
lrwxrwxrwx 1 root root 33 Sep 16 14:12 zfp1 -&gt; /etc/apache2/nodes-available/zfp1
lrwxrwxrwx 1 root root 33 Sep 16 14:36 zfp2 -&gt; /etc/apache2/nodes-available/zfp2</pre>
</li>
<li>Use the new system - Until this point we were just playing with files in a way that was completely transparent to apache. To start using this you need to make use of the Include functionality of apache&#8217;s configuration. I changed the reference to the single file (that we split in step 2) to be <i>Include nodes-enabled/zfp*</i>. By using a wildcard we can add more nodes without having to do anything to the actual server configuration. It also means we can use the load balancer for multiple clusters by just having differently named files.<br />
</p>
<pre class="code">&lt;Proxy balancer://mongrel_cluster&gt;
  Include nodes-enabled/zfp*
&lt;/Proxy&gt;</pre>
</li>
<li>Reload the config - Apache will happily run forever without re-reading its config file, so once you are comfortable with your new configuration, so you have to remember to tell it to reload.</li>
</ol>
<p>
All the above is still really only half the solution though. Actually, it is what makes controlling individual nodes possible, but it is a pretty manual process still. For this particular property we are using <a href="http://rubyhitsquad.com/Vlad_the_Deployer.html">Vlad the Deployer</a> to manage things, though I suspect you could use Capistrano or Puppet just as easily.<br />
</p>
<pre class="code">desc 'add a node to the server'
remote_task :add_node, :roles => :load_balancer do
  if ENV['node']
    run %{[ -f #{ apache_root }/nodes-available/#{ ENV['node'] } ] &#038;&#038; [ ! -f #{ apache_root }/nodes-enabled/#{ ENV['node'] } ] &#038;&#038; sudo ln -s #{ apache_root }/nodes-available/#{ ENV['node'] } #{ apache_root }/nodes-enabled/#{ ENV['node'] } &#038;&#038; sudo /etc/init.d/apache2 reload || echo "Node does not exist"}
  else
    p 'You need to specify a node to be able to add it. node=foo'
  end
end

desc 'remove a node from the server'
remote_task :remove_node, :roles => :load_balancer do
  if ENV['node']
    run %{[ -f #{ apache_root }/nodes-enabled/#{ ENV['node'] } ] &#038;&#038; sudo rm #{ apache_root }/nodes-enabled/#{ ENV['node'] } &#038;&#038; sudo /etc/init.d/apache2 reload || echo "Node does not exist"}
  else
    p 'You need to specify a node to be able to remove it. node=foo'
  end
end</pre>
<p>
(Yes, I know that the error messages are not very nice, or even accurate in a lot of situations, but it does the job which is all I require of it right now.)<br />
<br />
To enable a node you simply do a &#8216;rake lb:add_node node=zfpN&#8217; where lb is the namespace you created for your load balancer machine and N in this case is the node number. In this example there is only zfp1 and zfp2 but it should scale linearly.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=473</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=473</feedburner:origLink></item>
		<item>
		<title>Roodi</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/400763573/</link>
		<comments>http://adam.goucher.ca/?p=472#comments</comments>
		<pubDate>Tue, 23 Sep 2008 12:46:02 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Quality]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=472</guid>
		<description><![CDATA[I have been looking for a Ruby/Rails equivalent of checkstyle since I started working with it, but have only found a single orphaned project. Until yesterday that is. Yesterday&#8217;s Double Shot had a link to the Roodi project. Roodi stands for &#8216;Ruby Object Oriented Design Inferometer&#8217;, but essentially it is checkstyle for Ruby.

The Java community [...]]]></description>
			<content:encoded><![CDATA[<p>I have been looking for a Ruby/Rails equivalent of <a href="http://checkstyle.sourceforge.net/">checkstyle</a> since I started working with it, but have only found a single <a href="http://rubyforge.org/projects/checkr/">orphaned</a> project. Until yesterday that is. <a href="http://afreshcup.com/?p=948">Yesterday&#8217;s Double Shot</a> had a link to the <a href="http://roodi.rubyforge.org/">Roodi</a> project. Roodi stands for &#8216;Ruby Object Oriented Design Inferometer&#8217;, but essentially it is checkstyle for Ruby.<br />
<br />
The Java community has a rich set of guidelines to build static checks from, but the Ruby community seems to lack that cohesion. That is going to make for an interesting collection of checks over time and no doubt some discussion over what should be and checked and how. Here are the checks it currently does:<br />
</p>
<ul>
<li>AssignmentInConditionalCheck - Check for an assignment inside a conditional. It&#8216;s probably a mistaken equality comparison.</li>
<li>CaseMissingElseCheck - Check that case statements have an else statement so that all cases are covered.</li>
<li>ClassLineCountCheck - Check that the number of lines in a class is below the threshold.</li>
<li>ClassNameCheck - Check that class names match convention.</li>
<li>CyclomaticComplexityBlockCheck - Check that the cyclomatic complexity of all blocks is below the threshold.</li>
<li>CyclomaticComplexityMethodCheck - Check that the cyclomatic complexity of all methods is below the threshold.</li>
<li>EmptyRescueBodyCheck - Check that there are no empty rescue blocks.</li>
<li>ForLoopCheck - Check that for loops aren&#8216;t used (Use Enumerable.each instead)</li>
<li>MethodLineCountCheck - Check that the number of lines in a method is below the threshold.</li>
<li>MethodNameCheck - Check that method names match convention.</li>
<li>ModuleLineCountCheck - Check that the number of lines in a module is below the threshold.</li>
<li>ModuleNameCheck - Check that module names match convention.</li>
<li>ParameterNumberCheck - Check that the number of parameters on a method is below the threshold.</li>
</ul>
<p>
Thats all well and good, but a tool that is not run is just a clever piece of code. And relying on people to remember to run a tool is not a plan I would bet the house on. But that is why we have things like <a href="http://cruisecontrolrb.thoughtworks.com/">CruiseControl</a>.<br />
<br />
Here is a pretty heavily edited version of our Rakefile.</p>
<pre class="code">desc "Cruise Control"
namespace :cruise do
  output_dir = ENV["CC_BUILD_ARTIFACTS"]

  task :build do
    ...
    CruiseControl::invoke_rake_task 'cruise:roodi'
  end

  desc "Run the roodi tests"
  task :roodi do
    `roodi -config="#{RAILS_ROOT}/config/roodi.yml" "#{RAILS_ROOT}/app/**/*.rb" > #{output_dir}/roodi.txt`
  end
end</pre>
<p>
There is not (yet) a roodi_on_rails plugin, though I expect it is only a matter of time, so I just run the tool on the commandline and put the output in the place CruiseControl needs it to display it on the report page. The output is, to say the least, un-pretty but if the community backs this tool I can see it growing nice rspec like reports with links to the actual offending line.<br />
<br />
Oh, and here is config/roodi.yml, which is just the default configs for all the rules, but explicit is better than implicit.</p>
<pre class="code">AssignmentInConditionalCheck:    { }
CaseMissingElseCheck:            { }
ClassLineCountCheck:             { line_count: 300 }
ClassNameCheck:                  { pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ }
CyclomaticComplexityBlockCheck:  { complexity: 4 }
CyclomaticComplexityMethodCheck: { complexity: 8 }
EmptyRescueBodyCheck:            { }
ForLoopCheck:                    { }
MethodLineCountCheck:            { line_count: 20 }
MethodNameCheck:                 { pattern: !ruby/regexp /^[_a-z<>=\[\]|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ }
ModuleLineCountCheck:            { line_count: 300 }
ModuleNameCheck:                 { pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ }
ParameterNumberCheck:            { parameter_count: 5 }</pre>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=472</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=472</feedburner:origLink></item>
		<item>
		<title>Mirroring People</title>
		<link>http://feeds.feedburner.com/~r/AdamGoucher/~3/399890886/</link>
		<comments>http://adam.goucher.ca/?p=471#comments</comments>
		<pubDate>Mon, 22 Sep 2008 15:18:58 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Podcasts]]></category>

		<guid isPermaLink="false">http://adam.goucher.ca/?p=471</guid>
		<description><![CDATA[Michael has explored the usefulness of emotions as oracles when testing. I tend to explain this with a physical component as well; if your eyebrows move, it is a bug. Furrowed in frustration is a sign that we need to explain something better or set their expectations in a different way. Oppositely, when they go [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.developsense.com">Michael</a> has explored the usefulness of <a href="http://www.developsense.com/2007/05/lightning-talk-on-emotions-and-oracles.html">emotions as oracles</a> when testing. I tend to explain this with a physical component as well; if your eyebrows move, it is a bug. Furrowed in frustration is a sign that we need to explain something better or set their expectations in a different way. Oppositely, when they go up in surprise it can mean the same thing for different reasons.<br />
<br />
In this <a href="http://itc.conversationsnetwork.org/shows/detail3750.html">podcast</a>, <a href="http://faculty.bri.ucla.edu/institution/personnel?personnel_id=46207">Dr. Marco Iacoboni</a> discusses <a href="http://en.wikipedia.org/wiki/Mirror_neuron">&#8216;mirror neurons&#8217;</a> which allows us to empathize with people. The more neurons, the more empathetic. It so happens that one of the traits of people with autism is that they lack (or disfunction) of these neurons. (The first half of the podcast is the most interesting as it talks about the neurons and how they test for the presence of them. After that, it goes off about the election and a few other things which wasn&#8217;t nearly as interesting.)<br />
<br />
My first thought when listening was whether we want people in the testing craft to be those with more, or less mirror neurons. On further thought though I think it wouldn&#8217;t make much difference as the interaction in a pure testing context is between tester and machine; so no empathy necessary. One place I can think it would be very important is if their role is to debrief testing sessions. In that case you want someone who can pick up the nuances of what people are <i>actually</i> telling you through their voice, body language and inflection.<br />
<br />
Walking further out on the limb, I think a lack of empathy might also be valuable when logging bugs. If a developer is having a bad week, a highly empathetic tester might hold back on logging a bug as a result. A person with low empathy would log it anyways. If our primary objective as testers is to identify issues in the code then clearly the low empathy person is the one actually fulfilling the mission.<br />
<br />
To link this back to the shaky ground I&#8217;m thinking on here.<br />
<br />
There are a number of people who are successful in technology who have the minor form of autism called <a href="http://en.wikipedia.org/wiki/Asperger_syndrome">Asperger Syndrome</a>. BitTorrent creator Bram Cohen comes to mind immediately, but I recall reading an article which posited that Bill Gates has a number of the traits of this as well. Does anyone know of someone who has been successful as a tester that has been (clinically) identified as having AS or a more severe case of Autism? Although I have been testing for over 10 years now I have only worked closely enough with about a dozen testers to be able to make any sort of guess about them (rightly or wrongly). In my very limited sample set, I don&#8217;t think I have.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.goucher.ca/?feed=rss2&amp;p=471</wfw:commentRss>
		<feedburner:origLink>http://adam.goucher.ca/?p=471</feedburner:origLink></item>
	</channel>
</rss>
