<?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</title>
	<atom:link href="http://altentee.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://altentee.com</link>
	<description>Performance and Test Automation Experts</description>
	<lastBuildDate>Fri, 19 Feb 2010 23:57:29 +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>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>Securing MySQL Passwords</title>
		<link>http://altentee.com/2010/securing-mysql-passwords/</link>
		<comments>http://altentee.com/2010/securing-mysql-passwords/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 20:54:27 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=746</guid>
		<description><![CDATA[<p>There&#8217;s been a bit of buzz lately where MySQL databases have been compromised and user passwords being stored in plain text. Bad fu. It&#8217;s pretty simple to encrypt passwords in MySQL, here&#8217;s how you do it.</p>
<p>I&#8217;m using MySQL&#8217;s AES which is better than older standards. Basically 128 bit key encryption &#8230;</p>
<p>To begin, let&#8217;s create a [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a <a href="http://www.techcrunch.com/2009/12/14/rockyou-hacked/">bit of buzz</a> lately where MySQL databases have been compromised and user passwords being stored in plain text. Bad fu. It&#8217;s pretty simple to encrypt passwords in MySQL, here&#8217;s how you do it.</p>
<p><span id="more-746"></span>I&#8217;m using MySQL&#8217;s <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES</a> which is better than older standards. Basically 128 bit key encryption &#8230;</p>
<p>To begin, let&#8217;s create a demonstration table. e.g.<br />
CREATE TABLE users ( user_name VARCHAR(20) NOT NULL, user_password BLOB );</p>
<p>So now we have a simple table with a user_name field and user_password field. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql&amp;gt; <span style="color: #993333; font-weight: bold;">DESCRIBE</span> users;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">---------------+-------------+------+-----+---------+-------+</span>
<span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">FIELD</span>         <span style="color: #66cc66;">|</span> Type        <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #66cc66;">|</span> Extra <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">---------------+-------------+------+-----+---------+-------+</span>
<span style="color: #66cc66;">|</span> user_name     <span style="color: #66cc66;">|</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">|</span> NO   <span style="color: #66cc66;">|</span>     <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span>    <span style="color: #66cc66;">|</span>       <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">|</span> user_password <span style="color: #66cc66;">|</span> blob        <span style="color: #66cc66;">|</span> YES  <span style="color: #66cc66;">|</span>     <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span>    <span style="color: #66cc66;">|</span>       <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">---------------+-------------+------+-----+---------+-------+</span></pre></div></div>

<p>If we were creating a new user we would insert using the AES_ENCRYPT function. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> users <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'tim.koopmans'</span><span style="color: #66cc66;">,</span> AES_ENCRYPT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'mypassword'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Q4QjOyKANXj3qO'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>In this case I&#8217;ve used AES_ENCRYPT which encrypts a             string and returns a binary string. The AES             (Advanced Encryption Standard) algorithm is encoded with a 128-bit key. The second parameter is the key string, important to keep that secure!</p>
<p>On its own, this offers a good level of security. If the database was compromised the hacker will see information like this. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql&amp;gt; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> users;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+------------------+</span>
<span style="color: #66cc66;">|</span> user_name    <span style="color: #66cc66;">|</span> user_password    <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+------------------+</span>
<span style="color: #66cc66;">|</span> tim<span style="color: #66cc66;">.</span>koopmans <span style="color: #66cc66;">|</span> ??iu?hQ:???Ti?<span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+------------------+</span></pre></div></div>

<p>The problem with this, is that the user_password field can still be &#8216;guessed&#8217; via brute force methods. Every password that is the same i.e. &#8216;mypassword&#8217; will also have the same binary string.</p>
<p>You can add a <a href="http://en.wikipedia.org/wiki/Salt_%28cryptography%29">salt</a> to this by prefixing random digits to the plain text password before you encrypt. For example, we can use the first 12 digits of a UUID. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> users <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'joe.blow'</span><span style="color: #66cc66;">,</span> AES_ENCRYPT<span style="color: #66cc66;">&#40;</span>CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">LEFT</span><span style="color: #66cc66;">&#40;</span>UUID<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'mypassword'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Q4QjOyKANXj3qO'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>The result set now looks like this if compromised.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql&amp;gt; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> users;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+----------------------------------+</span>
<span style="color: #66cc66;">|</span> user_name    <span style="color: #66cc66;">|</span> user_password                    <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+----------------------------------+</span>
<span style="color: #66cc66;">|</span> tim<span style="color: #66cc66;">.</span>koopmans <span style="color: #66cc66;">|</span> ??iu?hQ:???Ti?<span style="color: #66cc66;">&#125;</span>                  <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">|</span> joe<span style="color: #66cc66;">.</span>blow     <span style="color: #66cc66;">|</span> ?M<span style="color: #66cc66;">&#125;</span><span style="color: #cc66cc;">69</span>?H?<span style="color: #cc66cc;">0</span>?H<span style="color: #66cc66;">&#125;</span>?<span style="color: #66cc66;">/</span><span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">.</span>?we<span style="color: #66cc66;">|</span>?A?P7ZD?R?   <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+----------------------------------+</span></pre></div></div>

<p>Every password that is encrypted should look different which will further complicate dictionary attacks.</p>
<blockquote><p>To determine a password from a stolen hash, an attacker cannot simply try common passwords (such as English language words or names). Rather, they must calculate the hashes of random characters (at least for the portion of the input they know is the salt), which is much slower.</p></blockquote>
<p>For best results, the value/length of your salt should be kept secret (and separate from your database). You should also keep the key secret of course!</p>
<p>Now if we ever need to extract the password we use the AES_DECRYPT function. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql&amp;gt; <span style="color: #993333; font-weight: bold;">SELECT</span> SUBSTR<span style="color: #66cc66;">&#40;</span>AES_DECRYPT<span style="color: #66cc66;">&#40;</span>user_password<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Q4QjOyKANXj3qO'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">13</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> password <span style="color: #993333; font-weight: bold;">FROM</span> users <span style="color: #993333; font-weight: bold;">WHERE</span> user_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'joe.blow'</span>;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------------+</span>
<span style="color: #66cc66;">|</span> password   <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------------+</span>
<span style="color: #66cc66;">|</span> mypassword <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------------+</span></pre></div></div>

<p>In this case we know the first 12 digits were the salt so I used SUBSTR after decrypting the hash to get the original password.</p>
<p>A couple of caveats, encrypting passwords in this fashion is reversible i.e. If your key gets compromised, then the hacker has access to all your passwords. Another option is to reverse the plain text and key parameters of AES_ENCRYPT, where the user&#8217;s password now becomes the key, and the key becomes the plain text. Even if the database and key is compromised, it is hard to crack user passwords. You would not be able to recover lost passwords of course &#8230; Security through obscurity!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/securing-mysql-passwords/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamic Data from JMeter JDBC Requests</title>
		<link>http://altentee.com/2010/dynamic-data-from-jmeter-jdbc-requests/</link>
		<comments>http://altentee.com/2010/dynamic-data-from-jmeter-jdbc-requests/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 06:45:17 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[jdbc]]></category>
		<category><![CDATA[jmeter]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=731</guid>
		<description><![CDATA[<p>A common requirement when load testing is to populate subsequent requests with dynamic data from previous requests. If you&#8217;re thinking about using a database to store static test data, such as usernames, paswords, credit card numbers etc then read on to find out how to extract this data at runtime and populate JMeter variables.</p>
<p>In this [...]]]></description>
			<content:encoded><![CDATA[<p>A common requirement when load testing is to populate subsequent requests with dynamic data from previous requests. If you&#8217;re thinking about using a database to store static test data, such as usernames, paswords, credit card numbers etc then read on to find out how to extract this data at runtime and populate JMeter variables.</p>
<p><span id="more-731"></span>In this example we&#8217;ll need to add a JDBC Connection Configuration to our test plan. This will define and control the way in which JMeter will access your database.</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.28.18-PM.png"><img class="alignleft size-full wp-image-732" title="Screen shot 2010-01-05 at 5.28.18 PM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.28.18-PM.png" alt="" width="647" height="423" /></a></p>
<p>Notice I&#8217;ve left the defaults for connection pool properties, although you may need to tweak this depending on how you&#8217;ll access the data. I&#8217;ve used a JDBC connection URL that accesses a local mysql server listening on port 3306. The database in use is called watirgrid</p>
<p>I&#8217;ve also defined the JDBC Driver class and specified the username / password to connect with.</p>
<p>Now we can make a JDBC request using the JDBC Request sampler. It will look something like this:<a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.31.52-PM.png"><img class="alignleft size-full wp-image-733" title="Screen shot 2010-01-05 at 5.31.52 PM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.31.52-PM.png" alt="" width="646" height="442" /></a></p>
<p>The Variable Name matches the JDBC Connection Config Variable Name i.e. mysql</p>
<p>I&#8217;m using a select statement that will print out results in a JSON-like format. That query is as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>
CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;[&quot;</span><span style="color: #66cc66;">,</span>
GROUP_CONCAT<span style="color: #66cc66;">&#40;</span>
CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;{email:'&quot;</span><span style="color: #66cc66;">,</span>email<span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;'&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;,login_count:'&quot;</span><span style="color: #66cc66;">,</span>login_count<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;'}&quot;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;]&quot;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">AS</span> json <span style="color: #993333; font-weight: bold;">FROM</span> users</pre></div></div>

<p>In doing this, it will return a result set that looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------------------------------------------------+</span>
<span style="color: #66cc66;">|</span> json                                            <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------------------------------------------------+</span>
<span style="color: #66cc66;">|</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#123;</span>email:<span style="color: #ff0000;">'tim.koops@gmail.com'</span><span style="color: #66cc66;">,</span>login_count:<span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------------------------------------------------+</span>
<span style="color: #cc66cc;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.00</span> sec<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Now we need to add a Post Processor Regex Extractor to the JDBC request as follows:</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.34.39-PM.png"><img class="alignleft size-full wp-image-734" title="Screen shot 2010-01-05 at 5.34.39 PM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.34.39-PM.png" alt="" width="172" height="40" /></a></p>
<p>The reason we do this is so we can extract the results from the JSON string returned by the database query. For example, to extract and populate a variable called ${email} our PPRE would look like this:</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.36.45-PM.png"><img class="alignleft size-full wp-image-735" title="Screen shot 2010-01-05 at 5.36.45 PM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.36.45-PM.png" alt="" width="652" height="236" /></a></p>
<p>Now we&#8217;re cooking! Add a Debug Sampler to confirm everything works as you&#8217;d expect. You should see results like this in the response data</p>
<pre>email=tim.koops@gmail.com
email_g=1
email_g0=email:'tim.koops@gmail.com'
email_g1=tim.koops@gmail.com
mysql=org.apache.jmeter.protocol.jdbc.config.DataSourceElement$DataSourceComponentImpl@10d69502
</pre>
<p>Attached is a demo test plan: <a href="http://altentee.com/wp-content/uploads/jdbc_example.jmx_.zip">jdbc_example.jmx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/dynamic-data-from-jmeter-jdbc-requests/feed/</wfw:commentRss>
		<slash:comments>3</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>Improved EBS snapshots on Amazon EC2</title>
		<link>http://altentee.com/2010/improved-ebs-snapshots-on-amazon-ec2/</link>
		<comments>http://altentee.com/2010/improved-ebs-snapshots-on-amazon-ec2/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 04:33:12 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[ec2]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=686</guid>
		<description><![CDATA[<p>So I&#8217;ve been working on a system where the MySQL instance on EC2 sporadically locks up (mysqld is zombied) during a snapshot process =)</p>
<p>Essentially the EC2 snapshot is triggered like this:</p>

system(&#34;xfs_freeze -f /vol&#34;)                        and die;
system(&#34;ec2-create-snapshot $vol -K $key -C $crt &#34;) and die;
system(&#34;xfs_freeze -u /vol&#34;)                        and die;

<p>This method is based on advice from here</p>
<p>Notice I [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve been working on a system where the <strong>MySQL</strong> instance on <strong>EC2</strong> sporadically locks up (mysqld is zombied) during a snapshot process =)</p>
<p>Essentially the <strong>EC2</strong> snapshot is triggered like this:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">system(&quot;xfs_freeze -f /vol&quot;)                        and die;
system(&quot;ec2-create-snapshot $vol -K $key -C $crt &quot;) and die;
system(&quot;xfs_freeze -u /vol&quot;)                        and die;</pre></div></div>

<p>This method is based on advice from <a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1663">here</a></p>
<p>Notice I am doing an <strong>xfs_freeze</strong> of the entire volume on which the mysql data sits. It is intended to be used with volume managers and hardware RAID devices that support the creation of snapshots such as EBS.<br />
<span id="more-686"></span></p>
<blockquote><p>The -f flag requests the specified XFS filesystem to be frozen from new modifications. When this is selected, all ongoing transactions in the filesystem are allowed to complete, new write system calls are halted, other calls which modify the filesystem are halted, and all dirty data, metadata, and log information are written to disk. Any process attempting to write to the frozen filesystem will block waiting for the filesystem to be unfrozen.</p>
<p>Note that even after freezing, the on-disk filesystem can contain information on files that are still in the process of unlinking. These files will not be unlinked until the filesystem is unfrozen or a clean mount of the snapshot is complete.</p>
<p>The -u flag is used to un-freeze the filesystem and allow operations to continue. Any filesystem modifications that were blocked by the freeze are unblocked and allowed to complete.</p></blockquote>
<p>EC2 recommends this for <strong>ec2-create-snapshot</strong>:</p>
<blockquote><p>When taking a snapshot of a file system, we recommend unmounting it first. This ensures the file system metadata is in a consistent state, that the &#8216;mounted indicator&#8217; is cleared, and that all applications using that file system are stopped and in a consistent state. Some file systems, such as xfs, can freeze and unfreeze activity so a snapshot can be made without unmounting.</p></blockquote>
<p>Clearly we don&#8217;t want to unmount the whole drive, so freezing the XFS volume is our best bet.</p>
<p>On a couple of occassions, we&#8217;ve seen the whole mysql server crash when a backup was taking place. The first symptoms displayed in logs is a long semaphore wait. This message is repeated for different threads:</p>
<pre>mysqld[26852]: InnoDB: Warning: a long semaphore wait:</pre>
<pre>mysqld[26852]: --Thread 46912644213072 has waited at ./../include/trx0sys.ic line 101 for 241.00 seconds the semaphore:</pre>
<pre>mysqld[26852]: X-lock on RW-latch at 0x2aaaaf01cc08 created in file buf0buf.c line 497</pre>
<pre>mysqld[26852]: a writer (thread id 46912644213072) has reserved it in mode  wait exclusive</pre>
<p>After about 10 minutes of this behaviour the server crashes. This is because 101 threads have made 101 connections where the max_connections=100. This only occurs whenever we are doing a snapshot in the background which makes me thing its a deadlock condition on the underlying filesystem.</p>
<pre>mysqld[26852]: InnoDB: We intentionally crash the server, because it appears to be hung.</pre>
<pre>mysqld[26852]: 091207 20:16:41InnoDB: Assertion failure in thread 46912625965392 in file srv0srv.c line 2097</pre>
<pre>mysqld[26852]: InnoDB: We intentionally generate a memory trap.</pre>
<pre>mysqld[26852]: InnoDB: Submit a detailed bug report to http://bugs.mysql.com.</pre>
<pre>mysqld[26852]: InnoDB: If you get repeated assertion failures or crashes, even</pre>
<pre>mysqld[26852]: InnoDB: immediately after the mysqld startup, there may be</pre>
<pre>mysqld[26852]: InnoDB: corruption in the InnoDB tablespace. Please refer to</pre>
<pre>mysqld[26852]: InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html</pre>
<pre>mysqld[26852]: InnoDB: about forcing recovery.</pre>
<pre>mysqld[26852]: 091207 20:16:41 - mysqld got signal 11 ;</pre>
<pre>mysqld[26852]: This could be because you hit a bug. It is also possible that this binary</pre>
<pre>mysqld[26852]: or one of the libraries it was linked against is corrupt, improperly built,</pre>
<pre>mysqld[26852]: or misconfigured. This error can also be caused by malfunctioning hardware.</pre>
<pre>mysqld[26852]: We will try our best to scrape up some info that will hopefully help diagnose</pre>
<pre>mysqld[26852]: the problem, but since we have already crashed, something is definitely wrong</pre>
<pre>mysqld[26852]: and this may fail.</pre>
<p>In panic mode, we restarted the whole server which was able to then recover from this error. But is there a more graceful recovery open to us?</p>
<p><strong>Alestic</strong> have released a revised version of the ec2-create-snapshot called<strong> <a href="http://alestic.com/2009/09/ec2-consistent-snapshot">ec2-consistent-snapshot </a></strong></p>
<blockquote><p>Here are some of the ways in which the ec2-consistent-snapshot program has improved over the original:</p>
<p>Command line options for passing in AWS keys, MySQL access information, and more.<br />
Can be run with or without a MySQL database on the file system. This lets you use the command to initiate snapshots for any EBS volume.<br />
Can be used with or without XFS file systems, though if you don’t use XFS, you run the risk of not having a consistent file system on EBS volume restore.<br />
Instead of using the painfully slow ec2-create-snapshot command written in Java, this Perl program accesses the EC2 API directly with orders of magnitude speed improvement.<br />
A preliminary FLUSH is performed on the MySQL database before the FLUSH WITH READ LOCK. This preparation reduces the total time the tables are locked.<br />
A preliminary sync is performed on the XFS file system before the xfs_freeze. This preparation reduces the total time the file system is locked.<br />
The MySQL LOCK now has timeouts and retries around it. This prevents horrible blocking interactions between the database lock, long running queries, and normal transactions. The length of the timeout and the number of retries are configurable with command line options.<br />
The MySQL FLUSH is done in such a way that the statement does not propagate through to slave databases, negatively impacting their performance and/or causing negative blocking interactions with long running queries.<br />
Cleans up MySQL and XFS locks if it is interrupted, if a timeout happens, or if other errors occur. This prevents a number of serious locking issues when things go wrong with the environment or EC2 API.<br />
Can snapshot EBS volumes in a region other than the default (e.g., eu-west-1).<br />
Can initiate snapshots of multiple EBS volumes at the same time while everything is consistently locked. This has been used to create consistent snapshots of RAIDed EBS volumes.</p>
<ul></ul>
</blockquote>
<p>Here&#8217;s hoping that this release fixes the problems with locking of the filesystem! Notice we don&#8217;t attempt to flush and lock since we are using the <strong>InnoDB</strong> engine.</p>
<p>Revised snapshot code looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># create snapshot
system(&quot;xfs_freeze -f /vol&quot;)                        and die;
system(&quot;ec2-consistent-snapshot --aws-access-key-id $key --aws-secret-access-key $secret --xfs-filesystem /vol $vol&quot;) and die;
system(&quot;xfs_freeze -u /vol&quot;)                        and die;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/improved-ebs-snapshots-on-amazon-ec2/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>7</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>14</slash:comments>
		</item>
	</channel>
</rss>
