<?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>Altentee &#187; Performance &#38; Test Automation Experts &#187; Altentee</title>
	<atom:link href="http://altentee.com/blogs/altentee/feed/" rel="self" type="application/rss+xml" />
	<link>http://altentee.com</link>
	<description>Performance and Test Automation Experts</description>
	<lastBuildDate>Fri, 06 Aug 2010 01:25:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to spoof Google Analytics traffic with JMeter</title>
		<link>http://altentee.com/2010/how-to-spoof-google-analytics-traffic-with-jmeter/</link>
		<comments>http://altentee.com/2010/how-to-spoof-google-analytics-traffic-with-jmeter/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 01:25:53 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[jmeter]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=933</guid>
		<description><![CDATA[<p>Recently a client asked Altentee to generate some load against their subscription to Google Analytics (GA). Calls to GA and other 3rd party monitoring tools are typically requests we blacklist or consider out of scope. So it was unusual to think the other way around, how would you performance test GA?</p>
<p></p>
<p>The solution as it turns [...]]]></description>
			<content:encoded><![CDATA[<p>Recently a client asked Altentee to generate some load against their subscription to Google Analytics (GA). Calls to GA and other 3rd party monitoring tools are typically requests we blacklist or consider out of scope. So it was unusual to think the other way around, how would you performance test GA?</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-08-06-at-10.28.24-AM.png"><img src="http://altentee.com/wp-content/uploads/Screen-shot-2010-08-06-at-10.28.24-AM.png" alt="" title="Screen shot 2010-08-06 at 10.28.24 AM" width="886" height="167" class="alignnone size-full wp-image-934" /></a></p>
<p>The solution as it turns out is quite simple. Google Analytics is well documented <a href="http://code.google.com/apis/analytics/docs/tracking/gaTrackingTroubleshooting.html">here</a> in terms of what query parameters constitute the GIF request that registers traffic.</p>
<p>The key parameters which need to be catered for when spoofing traffic are:<br />
utmn => Unique ID generated for each GIF request to prevent caching of the GIF image.<br />
utmhid => Another unique ID not documented but I think is related to AdSense<br />
plus all the GA cookies including utma, utmb, utmc and utmz</p>
<p>The best way to parametize this is to observe real traffic with a tool like FireBug in the Net(work) panel. That way you can make a copy of a real GIF request. Essentially you are going to fake the call to __utm.gif. An example request looks like this:</p>
<p>http://www.google-analytics.com/__utm.gif?utmwv=4.7.2&#038;utmn=123456789&#038;utmhn=www.altentee.com&#038;utmcs=UTF-8&#038;utmsr=1920&#215;1200&#038;utmsc=24-bit&#038;utmul=en-us&#038;utmje=1&#038;utmfl=10.0%20r45&#038;utmdt=AlteneeBlog&#038;utmhid=1697634062&#038;utmr=-&#038;utmp=%2F&#038;utmac=UA-12345678-3&#038;utmcc=__utma%3D199946558.28502083.1280297456.1280637882.1281056979.6%3B%2B__utmz%3D199946558.1280297456.1.1.utmcsr%3D(direct)%7Cutmccn%3D(direct)%7Cutmcmd%3D(none)%3B&#038;gaq=1</p>
<p>All you need to do to spoof traffic or generate page views to your GA account is make repeated calls to this URL after parametizing key fields previously mentioned. An example request in JMeter with corresponding parametized functions in bold (random and time) looks like this:</p>
<p>/__utm.gif?utmwv=4.7.2&#038;utmn=<strong>${__Random(10000000,60000000,utmn)}</strong>&#038;utmhn=www.altentee.com&#038;utmcs=UTF-8&#038;utmsr=1366&#215;768&#038;utmsc=24-bit&#038;utmul=en-us&#038;utmje=1&#038;utmfl=10.1%20r53&#038;utmdt=<strong>PerformanceTest</strong>&#038;utmhid=<strong>${__Random(100000000,900000000,utmhid)}</strong>&#038;utmr=-&#038;utmp=%2F&#038;utmac=UA-12345678-3&#038;utmcc=__utma%3D199946558.1448353202.<strong>${__time()}.${__time()}.${__time()}</strong>.4%3B%2B__utmz%3D199946558.<strong>${__time()}</strong>.1.1.utmcsr%3D(direct)%7Cutmccn%3D(direct)%7Cutmcmd%3D(none)%3B&#038;gaq=1</p>
<p>You could also build this URL from scratch although it&#8217;s much easier to copy and modify the target URL for the site you&#8217;re actually testing. Please don&#8217;t use the URLs above as I&#8217;ve faked other things like the Google Analytics account code (utmac). It&#8217;s also worth changing the page title (utmdt) so you can separate real traffic from the fake traffic generated during performance testing.</p>
<p>Build a simple test plan in JMeter with a HTTP sampler generating requests to the aforementioned URL, put in a constant timer (or similar) so you don&#8217;t spam GA&#8217;s servers and away you go. You can then measure response time to this service for as many threads as you like. I generated 10K page views in 5 minutes which was more than sufficient to satisfy the client&#8217;s requirements.</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-08-06-at-10.27.48-AM.png"><img src="http://altentee.com/wp-content/uploads/Screen-shot-2010-08-06-at-10.27.48-AM.png" alt="" title="Screen shot 2010-08-06 at 10.27.48 AM" width="896" height="324" class="alignnone size-full wp-image-935" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/how-to-spoof-google-analytics-traffic-with-jmeter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Authenticating Proxy with Webdriver and Watir</title>
		<link>http://altentee.com/2010/authenticating-proxy-with-webdriver-and-watir/</link>
		<comments>http://altentee.com/2010/authenticating-proxy-with-webdriver-and-watir/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 00:31:43 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[watir]]></category>
		<category><![CDATA[webdriver]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=927</guid>
		<description><![CDATA[<p>A question came up on stack overflow about how to route Watir through an authenticating proxy within your script.</p>
<p>The problem here is that you cannot auto authenticate to a proxy server using Chrome &#8211;proxy-server=my.proxy.com:3128 or using Firefox.</p>
<p>Chrome will always prompt you for a user name and password on an authenticating proxy when it starts up [...]]]></description>
			<content:encoded><![CDATA[<p>A question came up on stack overflow about how to <a href="http://stackoverflow.com/questions/2970777/how-do-i-route-watir-through-a-proxy-pragmatically">route Watir through an authenticating proxy within your script</a>.</p>
<p>The problem here is that you cannot auto authenticate to a proxy server using Chrome &#8211;proxy-server=my.proxy.com:3128 or using Firefox.</p>
<p>Chrome will always prompt you for a user name and password on an authenticating proxy when it starts up (via Webdriver or manually). Firefox will not prompt (when launched via WebDriver) and will silently fail.</p>
<p>I *almost* got this to work by modifying headers on the fly with a Firefox add on (<a href="https://addons.mozilla.org/en-US/firefox/addon/967/">Modify Headers</a>). Basic authentication is just base-64 encoded so you can force each request to authorize itself by modifying the Proxy-Authorization request header e.g.:<br />
<code>Proxy-Authorization	Basic asHJksaKHs87akhkjah7</code></p>
<p>However whilst this works for manually launched instances of Firefox, Webdriver launched instances would complain that the add on is not compatible with FF3.6.3 and so once again would fail. The other problem with this approach is that I couldn&#8217;t find a similar plugin for Chrome.</p>
<p>Eventually I gave in and went with a slightly more complicated workaround. That is, chaining an authenticated proxy (with squid) running on localhost with a cache_peer relationship to the authenticated proxy running out there  on the &#8216;tubes&#8217;. I had thought about using Webrick as a proxy (<a href="http://90kts.com/2008/httpwatch-a-free-alternative-using-ruby/">as per previous posts</a>) but lack of SSL support is a gotcha for me. Squid seemed most appropriate in this case:</p>
<p>To install squid from source:<br />
<code>cd /opt/src<br />
sudo curl -O http://www.squid-cache.org/Versions/v2/2.7/squid-2.7.STABLE9.tar.gz<br />
sudo tar xjf squid-2.7.STABLE9.tar.gz<br />
cd squid-2.7.STABLE9<br />
# I wanted SSL support for this<br />
./configure --enable-ssl<br />
make<br />
sudo make install</code></p>
<p>Edit the squid.conf (location is normally /etc/squid/squid.conf on linux):<br />
<code>sudo vim /usr/local/squid/etc/squid.conf</code></p>
<p><code># Don't want to run squid as root<br />
#  TAG: cache_effective_user<br />
cache_effective_user nobody<br />
#  TAG: cache_effective_group<br />
cache_effective_group wheel<br />
# Point this proxy to a peer cache, and provide the logon credentials<br />
#  TAG: cache_peer<br />
cache_peer proxy.altentee.com parent 3128 0 default no-query login=username:mypassword<br />
never_direct allow all<br />
# Allow access from my local private network<br />
#  TAG: cache_peer<br />
acl localnet src 10.0.0.0/0</code></p>
<p>Save changes and change ownership as appropriate:<br />
<code>sudo chown -R nobody:wheel /usr/local/squid</code></p>
<p>Initialize the cache and startup squid:<br />
<code>sudo /usr/local/squid/sbin/squid -z<br />
sudo /usr/local/squid/sbin/squid -D</code></p>
<p>Now you can configure firefox (using -ProfileManager) or chrome (using &#8211;proxy-server=127.0.0.1) to point to your local proxy server. This proxy will then authenticate on your behalf and peer all requests via the original parent.</p>
<p>A little long winded but achieves the outcome. Added side benefit is you&#8217;ve now got a local proxy (with access logs) that you can start doing interesting things with in your automation / performance tests like modifying headers and so forth.</p>
<p>Hope this helps!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/authenticating-proxy-with-webdriver-and-watir/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Regex in BrowserMob Scripts</title>
		<link>http://altentee.com/2010/regex-in-browsermob-scripts/</link>
		<comments>http://altentee.com/2010/regex-in-browsermob-scripts/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 00:27:25 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[browsermob]]></category>
		<category><![CDATA[selenium]]></category>

		<guid isPermaLink="false">http://altentee.com/2010/regex-in-browsermob-scripts/</guid>
		<description><![CDATA[<p>If you&#8217;re using an RBU or VU you may need to extract content from the previous response. For example, enumerate a link to a PDF file for subsequent download. </p>
<p>The BrowserMob interface has a handy findRegexMatches method you can call as follows:</p>

var link = browserMob.findRegexMatches(selenium.getHtmlSource(), 'href=&#34;(.+?pdf)&#34;');
browserMob.beginStep(&#34;16_download_content&#34;);
  browser.get(link[0], 200); 
browserMob.endStep();

<p>It takes a string input and [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re using an RBU or VU you may need to extract content from the previous response. For example, enumerate a link to a PDF file for subsequent download. </p>
<p>The BrowserMob interface has a handy findRegexMatches method you can call as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="js" style="font-family:monospace;">var link = browserMob.findRegexMatches(selenium.getHtmlSource(), 'href=&quot;(.+?pdf)&quot;');
browserMob.beginStep(&quot;16_download_content&quot;);
  browser.get(link[0], 200); 
browserMob.endStep();</pre></div></div>

<p>It takes a string input and regex pattern parameters. For the string input I am simply passing in the HTML source from the previous request based on a browser object:<br />
<code>var browser  = browserMob.getActiveHttpClient();</code></p>
<p>The regex pattern is self explanatory. The link object will be an array of matches; in this case I&#8217;m issuing a get request for the first link in the match array. You might want to add some more code to make this more robust e.g. if no links are found etc.</p>
<p>Pretty simple hey!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/regex-in-browsermob-scripts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Emulating Think Time and Pacing with BrowserMob</title>
		<link>http://altentee.com/2010/emulating-think-time-and-pacing-with-browsermob/</link>
		<comments>http://altentee.com/2010/emulating-think-time-and-pacing-with-browsermob/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 00:08:34 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[browsermob]]></category>
		<category><![CDATA[selenium]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=876</guid>
		<description><![CDATA[<p>If you come from the commercial toolset mindset, you might be interested in how we achieve think time and pacing when using alternatives such as BrowserMob.</p>
<p>Think Time
Think time, is normally defined as the amount of time a virtual user &#8216;thinks&#8217; between individual steps within a transaction. This time is usually excluded from response time measurements [...]]]></description>
			<content:encoded><![CDATA[<p>If you come from the commercial toolset mindset, you might be interested in how we achieve think time and pacing when using alternatives such as <a href="http://browsermob.com">BrowserMob</a>.</p>
<p><strong>Think Time</strong><br />
Think time, is normally defined as the amount of time a virtual user &#8216;thinks&#8217; between individual steps within a transaction. This time is usually excluded from response time measurements and is an important inclusion in terms of script behaviour. Having no think time means the virtual user will race through transactions more quickly than a normal user would which potentially creates unrealistic load. So how do we emulate think time behaviour in a BrowserMob script?</p>
<p>The BrowserMob replay engine drives Selenium scripts, so you will need to play in the JavaScript sandbox so to speak, in order to emulate think time. There&#8217;s some well documented ways to implement this on the BrowserMob blog <a href="http://blog.browsermob.com/help/creating-a-test/introducing-user-think-time/">here</a>.</p>
<p>The BrowserMob interface (<a href="http://static.browsermob.com/api/com/browsermob/api/BrowserMob.html">API documentation here</a>) has a pause method as follows:<br />
<code>browserMob.pause(15000); </code></p>
<p>This effectively pauses the user for a period of 15 seconds in the previous example.</p>
<p>The Selenium interface (<a href="http://static.browsermob.com/api/com/browsermob/api/Selenium.html">API documentation here</a>) also has a similar setSpeed method which will set the number of milliseconds to pause after each step elminating the need to specify individual pause statements between each step as follows:<br />
<code>selenium.setSpeed(2000);</code></p>
<p>If you would like to emulate some common think time settings as you might see in a LoadRunner script you can implement the following at the top of your RBU or VU scripts:</p>

<div class="wp_syntax"><div class="code"><pre class="js" style="font-family:monospace;">// Multiply think time by:
var think_time_multiple = 1;
&nbsp;
// Use random percentage for think time e.g. 50 - 100:
var think_time_percentage = 50 + (Math.random() * 100);
&nbsp;
// Limit think time to:
var think_time_limit = 0; 
&nbsp;
// Set think time to:
var think_time = 3; //seconds
&nbsp;
if(think_time_limit &gt; 0) {
  selenium.setSpeed(think_time_limit * 1000);
} else {
  selenium.setSpeed(think_time * think_time_multiple * (think_time_percentage/100) * 1000);
}</pre></div></div>

<p>If you need additional think time after steps then you can add the following statement where required:<br />
<code>browserMob.pause(3000 * think_time_multiple * (think_time_percentage/100)); </code></p>
<p><strong>Pacing</strong><br />
Some people like to control transaction volume/throughput by messing about with think time. I don&#8217;t favour this approach because you need to first be cognisant of how long each iteration will take including think time then adjust think time accordingly. Once it&#8217;s set (or hardcoded into your script) then the vusers are stuck with that setting. I much prefer the pacing concept, which determines how long a vuser should &#8216;wait&#8217; before starting the next iteration. This wait time is determined by elapsed time including any server side processing, not just user think time. So how do we emulate pacing in a BrowserMob script?</p>
<p>First I like to set some targets such as the transaction rate (per hour per user) and then calculate the pacing from this target. I also set a variable iterate to true, which comes into play in the main body of the script.</p>

<div class="wp_syntax"><div class="code"><pre class="js" style="font-family:monospace;">// Run logic
var transaction_rate = 10;  // Target transaction rate per hour per user
var pacing  = 60*60*1000 / transaction_rate;
var iterate = true;</pre></div></div>

<p>Now we&#8217;ve got the target and pacing set, we can get into the main logic. Let&#8217;s start an iteration.</p>

<div class="wp_syntax"><div class="code"><pre class="js" style="font-family:monospace;">while (iterate) {
  var start = new Date();
  browserMob.beginTransaction();
  ...</pre></div></div>

<p>Notice I&#8217;ve used a while loop which checks for the iterate boolean and creates a start date time stamp. I also initiate a BrowserMob transaction.</p>
<p>After we complete the iteration (which is essentially a bunch of BrowserMob steps) we can close the while loop with some pacing logic.</p>

<div class="wp_syntax"><div class="code"><pre class="js" style="font-family:monospace;">  ...
  // Calculate Pacing
  var finish  = new Date(); 
  var elapsed = finish.getTime() - start.getTime();
&nbsp;
  if (browserMob.isValidation()) {
    browserMob.log(&quot;Adjusted pacing would be &quot;+ (pacing - elapsed) + &quot; msecs&quot;);
    browserMob.log(&quot;or &quot; + Math.round(3600000 / (pacing - elapsed) ) + &quot; trans/hour&quot;);
    iterate = false;
  } else {
    if(pacing &gt; elapsed)
      browserMob.pause(pacing - elapsed);
  }
&nbsp;
  browserMob.endTransaction();
}</pre></div></div>

<p>This will calculate the finish date time stamp and then determine the difference between the previously calculated target pacing and the actual time elapsed. If there is a difference then the user will pause, otherwise it will just continue on to the next iteration. This basically allows you to target a set number of transactions per hour. When validating the script it will output these calculations to the log file.</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/emulating-think-time-and-pacing-with-browsermob/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Instant Website Tests with BrowserMob</title>
		<link>http://altentee.com/2010/instant-website-tests-with-browsermob/</link>
		<comments>http://altentee.com/2010/instant-website-tests-with-browsermob/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 00:40:28 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=782</guid>
		<description><![CDATA[<p>Can you afford a slow landing page?</p>
<p>Google AdWords page quality criteria are many, a prominent check being your landing page load time. A slow load time can lead to a lower quality score.</p>
<p>Make sure you&#8217;re not wasting effort on advertising campaigns. Altentee uses BrowserMob to help check website performance for clients from multiple locations. You [...]]]></description>
			<content:encoded><![CDATA[<p>Can you afford a slow landing page?</p>
<p>Google AdWords page quality criteria are many, a prominent check being your <a href="http://adwords.google.com/support/aw/bin/answer.py?hl=en&amp;answer=87144">landing page load time</a>. A slow load time can lead to a lower quality score.</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-06-at-9.11.48-AM.png"><img class="size-full wp-image-784 alignleft" title="Screen shot 2010-01-06 at 9.11.48 AM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-06-at-9.11.48-AM.png" alt="" width="274" height="95" /></a>Make sure you&#8217;re not wasting effort on advertising campaigns. <strong>Altentee </strong>uses <a href="http://browsermob.com">BrowserMob</a> to help check website performance for clients from multiple locations. You can run a free check using the form below.</p>
<form id="InstantTest" action="http://browsermob.com/instant-website-test" method="post">
<input id="InstantTest_url" class="urlTextBox default_value" name="url" type="text" value="yoursite.com" />
<input type="submit" value="go" /> (redirects to BrowserMob)<br />
</form>
<p>If you need help optimizing your landing page, or help with performance testing in general feel free to <a href="http://altentee.com/corporate/contact/">contact</a> <strong>Altentee</strong> today.</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/instant-website-tests-with-browsermob/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Harder, Better, Faster, Stronger [and Cheaper!]</title>
		<link>http://altentee.com/2010/harder-better-faster-stronger-and-cheaper/</link>
		<comments>http://altentee.com/2010/harder-better-faster-stronger-and-cheaper/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 05:04:13 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=692</guid>
		<description><![CDATA[<p>No, not the song but my adage for 2010 in my approach to performance testing in general. Readers of my old blog 90kts.com may have noticed the recent change to altentee.com. In 2009 I helped setup a boutique testing company called Altentee Pty Ltd. Read on for a quick advertisement about this new initiative &#8230;</p>
<p>We&#8217;re [...]]]></description>
			<content:encoded><![CDATA[<p>No, not the <a href="http://en.wikipedia.org/wiki/Harder,_Better,_Faster,_Stronger">song</a> but my adage for 2010 in my approach to performance testing in general. Readers of my old blog <a href="http://90kts.com/blogs/90kts/">90kts.com</a> may have noticed the recent change to <a href="http://altentee.com">altentee.com</a>. In 2009 I helped setup a boutique testing company called <strong>Altentee Pty Ltd</strong>. Read on for a quick advertisement about this new initiative &#8230;</p>
<p><span id="more-692"></span>We&#8217;re an Australian software performance and test automation specialist company based in Melbourne. We already have a global presence and employ some of the most experienced performance engineers available.</p>
<p>We pride ourselves on quality and cost effective solutions . Altentee offers alternative performance and test automation solutions using viable open source tool sets. This eliminates exorbitant license costs commonly associated with commercial tool sets. We&#8217;ve partnered with the team from <a href="http://browsermob.com">BrowserMob.com</a> for clients that want real-browser based performance testing. We&#8217;re also big fans of <a href="http://www.hyperic.com/">Hyperic</a> for performance monitoring, <a href="http://watir.com">Watir</a> for browser automation and <a href="http://jakarta.apache.org/jmeter/">JMeter</a> for protocol level performance tests.</p>
<p>Altentee&#8217;s mission is to deliver affordable and reliable performance and test automation alternatives to more traditional solutions.</p>
<p>Our goal is to deliver high quality, timely solutions whilst remaining affordable for any size organisation. Pay for the skills, not the tools and bring the focus back to your outcomes: delivering a fast, reliable system.</p>
<p>If you&#8217;re interested in what we do or know someone looking for performance and test automation solutions that won&#8217;t break the bank feel free to contact us via info@altentee.com</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/harder-better-faster-stronger-and-cheaper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Favourite SCiTE settings &#8230;</title>
		<link>http://altentee.com/2009/my-favourite-scite-settings/</link>
		<comments>http://altentee.com/2009/my-favourite-scite-settings/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 20:05:16 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/?p=260</guid>
		<description><![CDATA[<p>Well the subject goes without saying. I&#8217;ve been working on WinXP again lately and when I&#8217;m not around my favourite text editor on the mac (TextMate) I opt for SCiTE on windows. The following settings I find useful for this simple but powerful text editor. YMMV.</p>
<p>
# auto complete word
autocompleteword.automatic=1</p>
<p># advanced find and replace
find.replace.advanced=1</p>
<p> </p>
<p># force [...]]]></description>
			<content:encoded><![CDATA[<p>Well the subject goes without saying. I&#8217;ve been working on WinXP again lately and when I&#8217;m not around my favourite text editor on the mac (TextMate) I opt for SCiTE on windows. The following settings I find useful for this simple but powerful text editor. YMMV.</p>
<p><code><span id="more-260"></span><br />
# auto complete word<br />
autocompleteword.automatic=1</code></p>
<p><code># advanced find and replace<br />
find.replace.advanced=1</code></p>
<p><code> </code></p>
<p><code># force monospaced fonts<br />
font.base=$(font.monospace)<br />
font.small=$(font.monospace)<br />
font.comment=$(font.monospace)<br />
font.text=$(font.monospace)<br />
font.text.comment=$(font.monospace)<br />
font.embedded.base=$(font.monospace)<br />
font.embedded.comment=$(font.monospace)<br />
font.vbs=$(font.monospace)<br />
font.monospace=font:DejaVu Sans Mono,size:8</p>
<p># split horizontal instead of vertical<br />
split.vertical=0</p>
<p># Wrapping of long lines<br />
wrap=1</p>
<p># one instance of SciTE only<br />
check.if.already.open=1</p>
<p># save on deactivate<br />
save.on.deactivate=1</p>
<p># full path in title<br />
title.full.path=1</p>
<p># indentation<br />
tabsize=2<br />
indent.size=2<br />
use.tabs=1</p>
<p># max number of tabs<br />
buffers=20</p>
<p># reload file and prompt on activation<br />
load.on.activate=1</p>
<p># prompt me for any suspicous action<br />
are.you.sure.on.reload=1</p>
<p></code></p>
<p><code># show the status bar<br />
statusbar.visible=1<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/my-favourite-scite-settings/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Going Parallel &#8230;  distributed testing across a grid network using Watir</title>
		<link>http://altentee.com/2009/going-parallel-distributed-testing-across-a-grid-network-using-watir/</link>
		<comments>http://altentee.com/2009/going-parallel-distributed-testing-across-a-grid-network-using-watir/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 20:28:08 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[watir]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2009/going-parallel-distributed-testing-across-a-grid-network-using-watir/</guid>
		<description><![CDATA[<p>In my last post I made a tongue-in-cheek observation that load testing really doesn&#8217;t work by today&#8217;s perceived standards for web automation and testing.</p>
<p>Part of my grievance for that was based on frustration in dealing with different load testing platforms. Not frustration born out of incompetence, more the frustration born out writing tests for increasingly [...]]]></description>
			<content:encoded><![CDATA[<p>In my last <a href="http://90kts.com/blog/2009/why-load-testing-does-not-work-for-the-web-datetoday-36/"><strong>post</strong></a> I made a tongue-in-cheek observation that load testing really doesn&#8217;t work by today&#8217;s perceived standards for web automation and testing.</p>
<p>Part of my grievance for that was based on frustration in dealing with different load testing platforms. Not frustration born out of incompetence, more the frustration born out writing tests for increasingly complex browsers with an antiquated toolset.</p>
<p>That&#8217;s not to say that protocol based application load testing (or the languages they sit on) aren&#8217;t powerful in their own right. LoadRunner, JMeter et al. has their place in the load testing world. But I would like to relegate them to the background as useful, sometimes expensive tools to spin up the wheels so to speak. Nothing like a bit of JMeter infused fun to get the wheels smoking on your system under test. But for the real part,  measuring user experience on the web platform?<br />
<span id="more-292"></span><br />
<em>If you can&#8217;t wait to get started then I&#8217;d like to introduce <a href="http://browsermob.com"><strong>BrowserMob.com</strong></a>. Been around since mid 2008 and offers real browser testing using Selenium scripts distributed across a grid of EC2 computers. Reasonably priced, well documented and supported by the legendary Patrick Lightbody, founder of things like OpenQA and Selenium Remote Control.</em></p>
<p>But hang on a second, you don&#8217;t like Selenium right? Have zero budget? <strong>Love <a href="http://watir.com">Watir</a>?</strong> Well I&#8217;m working on a similar construct aptly called WatirGrid which also allows for distributed testing across a grid network using Watir. The engine (gem) itself is open source and you can get it as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">gem install watirgrid</pre></div></div>

<p>If you&#8217;d like to contribute please follow the <a href="http://github.com/90kts/watirgrid"><strong>WatirGrid</strong></a> project on github.</p>
<p><strong>The Basics</strong><br />
WatirGrid is built on Rinda which implements the Linda distributed computing paradigm in Ruby. According to Wikipedia: â€œLinda is a model of coordination and communication among several parallel processes operating upon objects stored in and retrieved from shared, virtual, associative memory.â€</p>
<p>In other words, WatirGrid allows multiple parallel processes to provide remote Watir objects in the form of tuple spaces across a grid network. This grid network is controlled by a ring server and looks a bit like this:</p>
<p><a href="http://altentee.com/wp-content/uploads/watirgrid_overview.png"><img class="alignnone size-full wp-image-543" title="watirgrid_overview" src="http://altentee.com/wp-content/uploads/watirgrid_overview.png" alt="" width="788" height="507" /></a></p>
<p><strong>Key Terminology</strong><br />
The <strong>controller</strong> implements a repository of tuples (tuple space) that can be accessed concurrently. The controller hosts the ring server which advertises these tuples across a grid network. Typically you will host one controller on a central machine.</p>
<p>The <strong>providers</strong> make remote Watir objects available to the tuple space hosted by the ring server. Typically you will host one or many providers on your grid network, for example, each PC may become a single provider of a Watir tuple in the form of an Internet Explorer, Firefox or Safari browser object.</p>
<p><strong>Simple Example</strong><br />
Pick a server to host the <em>controller</em> for the ring server and execute the following:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">  $ controller</pre></div></div>

<p>This should find your external facing IP and start the corresponding DRb and Ring Servers:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">  DRb server started on : druby://143.238.105.61:11235
  Ring server started on: druby://143.238.105.61:12358</pre></div></div>

<p>On each client PC, host the <em>provider</em> for the distributed (DRb) Watir objects</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">  $  provider</pre></div></div>

<p>This should find the recently started Ring Server and register a tuple for the Watir object:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">  DRb server started on : druby://143.238.105.61:11236
  Ring server found on  : druby://143.238.105.61:12358
  New tuple registered  : druby://143.238.105.61:12358</pre></div></div>

<p>You will now be able to execute commands across remote browsers on your grid network.<br />
e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  grid = <span style="color:#6666ff; font-weight:bold;">Watir::Grid</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:ring_server_port</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006666;">12358</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  grid.<span style="color:#9900CC;">start</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:quantity</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006666;">1</span>, <span style="color:#ff3333; font-weight:bold;">:read_all</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  threads = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  grid.<span style="color:#9900CC;">browsers</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>browser<span style="color:#006600; font-weight:bold;">|</span>
    threads <span style="color:#006600; font-weight:bold;">&amp;</span>lt;<span style="color:#006600; font-weight:bold;">&amp;</span>lt; <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">new</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      b = browser<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:object</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">new_browser</span>
      b.<span style="color:#9900CC;">goto</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;http://www.google.com&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      b.<span style="color:#9900CC;">text_field</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span>, <span style="color:#996600;">'q'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">set</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;watirgrid&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      b.<span style="color:#9900CC;">button</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span>, <span style="color:#996600;">&quot;btnI&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">click</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  threads.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>thread<span style="color:#006600; font-weight:bold;">|</span> thread.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>You may wish to host the controller and providers on different machines in a real scenario. You can specify things like server hostnames, ports and access control lists for each of the different types of servers. For more help see:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">  $  controller --help
  Usage: controller [options]
  Specific options:
      -H, --drb-server-host HOST       Specify DRb Server interface to host on
      -d, --drb-server-port PORT       Specify DRb Server port to listen on
      -h, --ring-server-host HOST      Specify Ring Server interface to host on
      -r, --ring-server-port PORT      Specify Ring Server port to listen on
      -a, --access-control-list ACLS   Specify a comma separated Access Control List
      -l, --log-level LEVEL            Specify log level {DEBUG|INFO|ERROR}
          --help                       Show this message
&nbsp;
  $  provider --help
  Usage: provider [options]
  Specific options:
      -H, --drb-server-host HOST       Specify DRb Server interface to host on
      -d, --drb-server-port PORT       Specify DRb Server port to listen on
      -h, --ring-server-host HOST      Specify Ring Server host to connect to
      -r, --ring-server-port PORT      Specify Ring Server port to broadcast on
      -b, --browser-type TYPE          Specify browser type to register {ie|firefox|safari}
      -a, --access-control-list ACLS   Specify a comma separated Access Control List
      -l, --log-level LEVEL            Specify log level {DEBUG|INFO|ERROR}
          --help                       Show this message</pre></div></div>

<p>Need more help?</p>
<p>Keep an eye on the <a href="http://wiki.github.com/90kts/watirgrid"><strong>wiki</strong></a> and the <a href="http://github.com/90kts/watirgrid/tree/master/spec/"><strong>rspec</strong></a> test cases!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/going-parallel-distributed-testing-across-a-grid-network-using-watir/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Why Load Testing Does Not Work for the Web `Date::today &gt;&gt; 36`</title>
		<link>http://altentee.com/2009/why-load-testing-does-not-work-for-the-web-datetoday-36/</link>
		<comments>http://altentee.com/2009/why-load-testing-does-not-work-for-the-web-datetoday-36/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 21:20:50 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2009/why-load-testing-does-not-work-for-the-web-datetoday-36/</guid>
		<description><![CDATA[<p>I was going to write why LoadRunner does not work for the web as it is today and into the foreseeable future, but decided against that because I don&#8217;t think the following points are necessarily limited to a specific toolset.</p>
<p>Load testing does not work for web as it is today primarily because&#8230;

1. Load testing tool [...]]]></description>
			<content:encoded><![CDATA[<p>I was going to write why LoadRunner does not work for the web as it is today and into the foreseeable future, but decided against that because I don&#8217;t think the following points are necessarily limited to a specific toolset.</p>
<p>Load testing does not work for web as it is today primarily because&#8230;<br />
<span id="more-259"></span><br />
<em>1. Load testing tool languages are not flexible enough. </em><br />
Load testing tools are in need of a major overhaul. Consider <a href="https://h10078.www1.hp.com/cda/hpms/display/main/hpms_content.jsp?zn=bto&#038;cp=1-11-126-17%5E8_4000_100__"><strong>LoadRunner</strong></a>, the majority of your scripts will be specified in C or proprietary API calls such as lr_ statements. String manipulation for example, whilst possible is extremely clunky and requires oodles of C code. <strong><a href="http://90kts.com/blog/2009/regex-search-and-replace-in-loadrunner/">Lack of proper regex</a></strong> or xpath support limits script flexibility in terms of parsing the necessary contents of web page and ajax calls. Don&#8217;t even get me started on ajax! Similar complaints for <a href="http://jakarta.apache.org/jmeter/"><strong>JMeter</strong></a>. Although better support for regex you can really only edit test plans via the GUI. You&#8217;ll go cross-eyed looking at test plans in xml. I think <a href="http://grinder.sourceforge.net/"><strong>the Grinder</strong></a> is the closest product I&#8217;ve seen that supports flexibility as you can write tests in Jython which provides more flexibility in terms of scripting.</p>
<p><em>2. We&#8217;re still stuck in record and playback mode.</em><br />
We really haven&#8217;t advanced like our automation brethren. Part of the big sell by commercial load testing companies is &#8220;Look it&#8217;s easy, just hit the red button and play it back when you&#8217;re finished!&#8221;. Bollocks to that, we know that never works. A dream load testing tool would support the ability to hand-code your statements and be editable in a text editor! In a similar fashion to <a href="http://watir.com"><strong>watir</strong></a>.</p>
<p>The dream tool would look like:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">vusers.<span style="color:#9900CC;">start</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">100</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  browser.<span style="color:#9900CC;">goto</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'url'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  browser.<span style="color:#9900CC;">button</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:text</span>, <span style="color:#006600; font-weight:bold;">/</span>Continue<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">click</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Instead load testing scripts in LoadRunner look something like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">web_submit_data<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;transaction&quot;</span><span style="color: #339933;">,</span>
<span style="color: #ff0000;">&quot;Action=https://someurl/I/have/to/keep/correlating/damn/it&quot;</span><span style="color: #339933;">,</span>
<span style="color: #ff0000;">&quot;Method=POST&quot;</span>
<span style="color: #ff0000;">&quot;RecContentType=&quot;</span>text<span style="color: #339933;">/</span>html<span style="color: #ff0000;">&quot;,
&quot;</span>Mode<span style="color: #339933;">=</span>HTML<span style="color: #ff0000;">&quot;,
&quot;</span>ITEMDATA<span style="color: #339933;">,</span>
<span style="color: #ff0000;">&quot;Name=L_3_0_0_1_0_1&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Value={another_value_I_have_to_correlate}&quot;</span><span style="color: #339933;">,</span>
<span style="color: #ff0000;">&quot;Name=L_3_0_0_2_0_1&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Value={maybe_paramatize_this_one}&quot;</span><span style="color: #339933;">,</span>
ENDITEM<span style="color: #339933;">,</span>
LAST<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>We are of course talking about very different technologies. Watir automation scripts driving real browsers with win32ole, whereas most load testing tools are injecting traffic at the protocol layer. If a typical end to end scenario has 30 steps, this can amount to some 2000+ lines of code thanks to the extra verbosity of having to specify all the form values and so forth. This also means you have oodles of code to correlate and parametize. It&#8217;s not something you want to hand code, the quickest path is to record (unfortunately). <a href="http://browsermob.com"><strong>BrowserMob</strong></a> is the closest online provider I&#8217;ve seen that overcomes this, supporting load tests written as selenium scripts. Problem is, we need a solution for all those non-public facing companies, the bulk of where I do my work at!</p>
<p><em>3. No real code versioning. </em><br />
Changes to the UI will break your script! One can implement their own code versioning as I have recently begun to do with git but there really should be built in support for this. That aside, you revision your code but effectively blast it away every time you hit the red record button. Reason? Each recording can look vastly different to the last. It only takes one form value L_3_0_0_1_0_1 to change to L_3_0_0_1_0_2 or one block of code executed by an ajax call to shift to cause mass confusion. Versioning your code *may* pick this change up, but only if you got the power of the diff! Diffing just got a little harder. Shoot back 10 years ago and diffing for correlation would have been a cinch. Wind forward to today with hundreds of ajax or json calls and correlation can be a nightmare. Windiff struggles. <a href="http://code.google.com/p/daisydiff/"><strong>Daisydiff</strong></a> does a much better job highlighting differences by line and by column. This approach kind of works in a waterfall test environment. Throw in a twice weekly code drop in your performance test environment and watch your scripts break. Agile anyone?</p>
<p>So if I was an uber-elite programmer what would I do to move loadtesting into the current decade?<br />
<em>1. Develop a load-testing tool that is based on a flexible scripting language such as Ruby.<br />
2. Get rid of the record button and provide free text editors to the world!<br />
3. Provide a framework that can be versioned and easily detect changes in the system under test.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/why-load-testing-does-not-work-for-the-web-datetoday-36/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>GMail Getting Things Done &#8211; a poor man&#8217;s version</title>
		<link>http://altentee.com/2009/gmail-getting-things-done-a-poor-mans-version/</link>
		<comments>http://altentee.com/2009/gmail-getting-things-done-a-poor-mans-version/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 22:21:37 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2009/gmail-getting-things-done-a-poor-mans-version/</guid>
		<description><![CDATA[<p>I really like the concept of Getting Things Done. I&#8217;m also a fan of Inbox Zero. Well, at least try to be. Here&#8217;s how I implement GTD using my gmail account&#8230;

First I create four labels:
label:g-action
label:g-waiting-on
label:g-some-day
label:g-finished</p>
<p>Now I can tag emails in my inbox when I view them with the keyboard shortcut l->a for action, w for [...]]]></description>
			<content:encoded><![CDATA[<p>I really like the concept of <a href="http://en.wikipedia.org/wiki/Getting_Things_Done"><strong>Getting Things Done</strong></a>. I&#8217;m also a fan of <a href="http://inboxzero.com/"><strong>Inbox Zero</strong></a>. Well, at least try to be. Here&#8217;s how I implement GTD using my gmail account&#8230;<br />
<span id="more-255"></span><br />
First I create four labels:<br />
label:g-action<br />
label:g-waiting-on<br />
label:g-some-day<br />
label:g-finished</p>
<p>Now I can tag emails in my inbox when I view them with the keyboard shortcut <code>l->a</code> for action, <code>w</code> for waiting-on and so forth.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/10/labels_action.png' title='labels_action.png'><img src='http://90kts.com/blog/wp-content/uploads/2009/10/labels_action.png' alt='labels_action.png' /></a></p>
<p>I make a habit of reading, deleting or tagging each email that comes through my inbox. Hence I get closer to Inbox Zero.</p>
<p>I also use the Quick Links feature available through GMail Labs.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/10/quick_links.png' title='quick_links.png'><img src='http://90kts.com/blog/wp-content/uploads/2009/10/quick_links.png' alt='quick_links.png' /></a></p>
<p>I then create links to the 4 labels by searching on the syntax described previously.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/10/quick_links_labels.png' title='quick_links_labels.png'><img src='http://90kts.com/blog/wp-content/uploads/2009/10/quick_links_labels.png' alt='quick_links_labels.png' /></a></p>
<p>There are of course plenty of apps and additional plugins for specific browsers that achieve the same thing. I just like this approach because it is generally OS/browser independent which means I can take it with me from workplace to workplace (provided they let me access my gmail account of course!)</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/gmail-getting-things-done-a-poor-mans-version/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
