<?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; 90kts</title>
	<atom:link href="http://altentee.com/blogs/90kts/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>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>5</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>2</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>
		<item>
		<title>Watir Powered LoadRunner Scripts</title>
		<link>http://altentee.com/2009/watir-powered-loadrunner-scripts/</link>
		<comments>http://altentee.com/2009/watir-powered-loadrunner-scripts/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 09:16:31 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[loadrunner]]></category>
		<category><![CDATA[watir]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2009/watir-powered-loadrunner-scripts/</guid>
		<description><![CDATA[<p>Here&#8217;s an idea&#8230; Ever been in a LoadRunner contract where you&#8217;ve got a ton of scripts to write for business transactions that have many many design steps?</p>
<p>Even worse, have you had to write those scripts against a development environment with an unstable code base and shocking performance? Sound familiar? Ever felt the frustration of re-recording [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s an idea&#8230; Ever been in a LoadRunner contract where you&#8217;ve got a ton of scripts to write for business transactions that have many many design steps?</p>
<p>Even worse, have you had to write those scripts against a development environment with an unstable code base and shocking performance? Sound familiar? Ever felt the frustration of re-recording manual test cases back into LoadRunner in said environments. Why wouldn&#8217;t you just automate the script recording process?</p>
<p><span id="more-254"></span><br />
Well if you&#8217;re in a LoadRunner shop there&#8217;s probably a QTP license floating around. However there&#8217;s a great alternative with Ruby, specifically <a href="http://watir.com"><strong>Web Application Testing In Ruby</strong></a>.</p>
<p>The gist is that you setup your manual test case using a watir script, then re-record your LoadRunner scripts using those watir scripts as the driver. The benefits are many:</p>
<p>1. Reduce user input errors when recording the LoadRunner scripts.<br />
2. Have a consistent way of re-recording LoadRunner scripts based on the same input delivered by the watir script.<br />
3. Diffing for correlation becomes easier because of consistency between multiple recordings of the same script.<br />
4. Watir scripts are easier to maintain than LoadRunner scripts.<br />
5. You can incorporate other Ruby gems into your watir scripts to assist with repetitive tasks during recording. For example, I copy transaction names to the clipboard between each step so I can easily paste them into transaction start timers.<br />
6. Watir scripts can double as a smoke test which you can run in parallel with load tests that use only virtual users.<br />
7. Watir scripts (and sampling response time from a real browser) will incorporate other factors such as client render time. Something which vusers really can&#8217;t do.</p>
<p>Downside is that you need to do a little more preparation than you might have to if you&#8217;re just following a manual test case. Once you have a framework for creating your watir script, this becomes easier. I figure it takes me about 1 hour to script up an end to end transaction that might have around 30 sub transactions (or design steps).</p>
<p>So what do you need to get started?</p>
<p>Firstly to install watir, follow these instructions <a href="http://watir.com/installation/"><strong>here</strong></a>.</p>
<p>Come up with a framework for driving your manual test cases. There&#8217;s plenty of examples out there on how to make bullet proof frameworks driven from a variety of sources. Alister shares some good tips <a href="http://watirmelon.com/2009/09/08/creating-a-watir-framework-using-test-unit-and-roo/"><strong>here</strong></a>.</p>
<p>Here&#8217;s a simple framework to get you started.</p>
<p>I have a helpers class that fires up the browser (attaches to the window that LoadRunner spawns) and some common methods for starting/stopping transaction timers and writing out information to a logfile. It looks like this.<br />
<strong>helpers.rb</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'watir'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'logger'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'win32/clipboard'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'dl'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'win32/sound'</span>
<span style="color:#9966CC; font-weight:bold;">include</span> Win32
&nbsp;
logfile = <span style="color:#996600;">'C:<span style="color:#000099;">\t</span>emp<span style="color:#000099;">\o</span>utput.log'</span>
<span style="color:#0066ff; font-weight:bold;">@log</span> = <span style="color:#CC00FF; font-weight:bold;">Logger</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>logfile, <span style="color:#996600;">'daily'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#0066ff; font-weight:bold;">@log</span>.<span style="color:#9900CC;">info</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>New test started at &quot;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#0066ff; font-weight:bold;">@log</span>.<span style="color:#9900CC;">datetime_format</span> = <span style="color:#996600;">&quot;%H:%M:%S&quot;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># if I want each step to start on the minute</span>
<span style="color:#008000; font-style:italic;"># useful when tracing back through profile logs</span>
<span style="color:#008000; font-style:italic;"># on the target server</span>
<span style="color:#0066ff; font-weight:bold;">@staggered</span> = <span style="color:#0000FF; font-weight:bold;">false</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># pause after each step to prompt you to</span>
<span style="color:#008000; font-style:italic;"># stop a transaction time or start a new one</span>
<span style="color:#0066ff; font-weight:bold;">@pause</span> = <span style="color:#0000FF; font-weight:bold;">false</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># setup a clipboard object to copy transaction names to</span>
<span style="color:#0066ff; font-weight:bold;">@clipboard</span> <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#6666ff; font-weight:bold;">Win32::Clipboard</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># setup my browser object and attach to a running browser</span>
<span style="color:#008000; font-style:italic;"># spawned by the loadrunner recording engine</span>
<span style="color:#0066ff; font-weight:bold;">@b</span> <span style="color:#006600; font-weight:bold;">||</span>=<span style="color:#6666ff; font-weight:bold;">Watir::IE</span>.<span style="color:#9900CC;">attach</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#006600; font-weight:bold;">/</span>FOOBAR<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># alternatively start a new browser</span>
<span style="color:#008000; font-style:italic;">#~ @b ||=Watir::Browser.new</span>
<span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">visible</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
<span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">speed</span> = <span style="color:#ff3333; font-weight:bold;">:fast</span>
<span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">bring_to_front</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># display a simple message box with a dodgy sound</span>
<span style="color:#008000; font-style:italic;"># to grab your attention</span>
<span style="color:#9966CC; font-weight:bold;">def</span> message_box<span style="color:#006600; font-weight:bold;">&#40;</span>txt, title=APP_TITLE, buttons=<span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  5.<span style="color:#9900CC;">upto</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">10</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span> Sound.<span style="color:#9900CC;">beep</span><span style="color:#006600; font-weight:bold;">&#40;</span>i<span style="color:#006600; font-weight:bold;">*</span><span style="color:#006666;">1000</span>,<span style="color:#006666;">30</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
  user32 = DL.<span style="color:#9900CC;">dlopen</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'user32'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  msgbox = user32<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'MessageBoxA'</span>, <span style="color:#996600;">'ILSSI'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  r, rs = msgbox.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span>, txt, title, buttons<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0000FF; font-weight:bold;">return</span> r
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># a start timer method</span>
<span style="color:#9966CC; font-weight:bold;">def</span> timer_start
&nbsp;
  <span style="color:#008000; font-style:italic;"># figure out how long to sleep if staggered start is true</span>
  now = <span style="color:#CC00FF; font-weight:bold;">DateTime</span>.<span style="color:#9900CC;">now</span>
  diff = <span style="color:#006666;">60</span> <span style="color:#006600; font-weight:bold;">-</span> now.<span style="color:#9900CC;">sec</span>
  <span style="color:#CC0066; font-weight:bold;">sleep</span> diff <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@staggered</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># empty clipboard and copy current transaction name to it</span>
  <span style="color:#0066ff; font-weight:bold;">@clipboard</span>.<span style="color:#9900CC;">empty</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@clipboard</span>.<span style="color:#9900CC;">set_data</span><span style="color:#006600; font-weight:bold;">&#40;</span>@t<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># prompt you to start a new transaction if pause is true</span>
  message_box<span style="color:#006600; font-weight:bold;">&#40;</span>@t, <span style="color:#996600;">&quot;Start Transaction&quot;</span>, <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@pause</span>
&nbsp;
  <span style="color:#0066ff; font-weight:bold;">@start_time</span> = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># end timer method</span>
<span style="color:#9966CC; font-weight:bold;">def</span> timer_end
  <span style="color:#0066ff; font-weight:bold;">@end_time</span> = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># prompt you to stpo end a transaction if pause is true</span>
  message_box<span style="color:#006600; font-weight:bold;">&#40;</span>@t, <span style="color:#996600;">&quot;End Transaction&quot;</span>, <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@pause</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># figure out elapsed time</span>
  <span style="color:#0066ff; font-weight:bold;">@elapsed_time</span> = <span style="color:#006600; font-weight:bold;">&#40;</span>@end_time <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#0066ff; font-weight:bold;">@start_time</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">*</span> <span style="color:#006666;">1000</span>
  tab = <span style="color:#996600;">&quot;<span style="color:#000099;">\t</span>&quot;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># write it all to you logger</span>
  <span style="color:#0066ff; font-weight:bold;">@log</span>.<span style="color:#9900CC;">info</span><span style="color:#006600; font-weight:bold;">&#40;</span>@start_time.<span style="color:#9900CC;">to_f</span>.<span style="color:#9900CC;">to_s</span> <span style="color:#006600; font-weight:bold;">+</span> tab <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#0066ff; font-weight:bold;">@end_time</span>.<span style="color:#9900CC;">to_f</span>.<span style="color:#9900CC;">to_s</span>  <span style="color:#006600; font-weight:bold;">+</span> tab \
  <span style="color:#006600; font-weight:bold;">+</span> tab <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#0066ff; font-weight:bold;">@start_time</span>.<span style="color:#9900CC;">to_s</span> <span style="color:#006600; font-weight:bold;">+</span> tab <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#CC0066; font-weight:bold;">sprintf</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'%-60s'</span>, <span style="color:#0066ff; font-weight:bold;">@t</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> tab <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#CC0066; font-weight:bold;">sprintf</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'%10s'</span>, <span style="color:#0066ff; font-weight:bold;">@elapsed_time</span>.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># a simple sync method to wait for text on a scren</span>
<span style="color:#9966CC; font-weight:bold;">def</span> sync<span style="color:#006600; font-weight:bold;">&#40;</span>text<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#6666ff; font-weight:bold;">Watir::Waiter</span>.<span style="color:#9900CC;">wait_until</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">text</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>text<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Now your manual test case in ruby should look pretty simple. I typically rely on things like the :name, :text or :id attributes of html elements depending on how the application was written by the developers. The manual test case will look something like this.<br />
<strong>001_test_case.rb</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'helpers.rb'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">begin</span>
&nbsp;
  <span style="color:#0066ff; font-weight:bold;">@t</span> = <span style="color:#996600;">&quot;INIT&quot;</span>
  timer_start
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">goto</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'https://foobar/wps/myportal'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  timer_end
&nbsp;
  <span style="color:#0066ff; font-weight:bold;">@t</span> = <span style="color:#996600;">&quot;LOGIN&quot;</span>
  timer_start
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<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;">&quot;username&quot;</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;yoohoo&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<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;">&quot;password&quot;</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;foobar&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">button</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:index</span>, <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">click</span>
  timer_end
&nbsp;
  <span style="color:#0066ff; font-weight:bold;">@t</span> = <span style="color:#996600;">&quot;FOOBAR_03a_03_Tab&quot;</span>
  timer_start
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">link</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>FOOBAR<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">click</span>
  timer_end
&nbsp;
  <span style="color:#0066ff; font-weight:bold;">@t</span> = <span style="color:#996600;">&quot;FOOBAR_03a_04_FOOBAR_Tab&quot;</span>
  timer_start
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">link</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>FOOBAR<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">click</span>
  sync<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;New FOOBAR&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  timer_end
&nbsp;
  <span style="color:#0066ff; font-weight:bold;">@t</span> = <span style="color:#996600;">&quot;FOOBAR_03a_27_Record_Notes&quot;</span>
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">text_field</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#996600;">&quot;PC_7_C5L40JR2001F002J5MT98S28H6__L_8_0_1_0_14_1_1&quot;</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;Justification&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  timer_start
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<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>Save<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">click</span>
  timer_end
&nbsp;
  <span style="color:#0066ff; font-weight:bold;">@t</span> = <span style="color:#996600;">&quot;FOOBAR_03a_28_Save_And_Foobaz&quot;</span>
  timer_start
  <span style="color:#0066ff; font-weight:bold;">@b</span>.<span style="color:#9900CC;">link</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>Save <span style="color:#006600; font-weight:bold;">&amp;</span> Foobaz<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">click</span>
  timer_end
&nbsp;
  <span style="color:#008000; font-style:italic;"># etc ...</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">Exception</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
  <span style="color:#0066ff; font-weight:bold;">@log</span>.<span style="color:#9900CC;">error</span><span style="color:#006600; font-weight:bold;">&#40;</span>@start_time.<span style="color:#9900CC;">to_i</span>.<span style="color:#9900CC;">to_s</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\t</span>&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#CC0066; font-weight:bold;">sprintf</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'%-60s'</span>, <span style="color:#0066ff; font-weight:bold;">@trans</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\t</span>Error<span style="color:#000099;">\n</span>&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> e<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Running this test case will output a log file to C:\temp\output.log that looks like this.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">New test started at Thu Oct 08 20:37:48 +1100 2009
1254994670.936  1254994671.576          Thu Oct 08 20:37:50 +1100 2009  INIT                                                                 640.0
1254994671.576  1254994678.233          Thu Oct 08 20:37:51 +1100 2009  LOGIN                                                               6657.0
1254994678.233  1254994694.123          Thu Oct 08 20:37:58 +1100 2009  FOOBAR_03a_03_Tab                                          15890.0
1254994694.123  1254994696.014          Thu Oct 08 20:38:14 +1100 2009  FOOBAR_03a_04_FOOBAR_Tab                                      1891.0
1254994717.171  1254994727.608          Thu Oct 08 20:38:37 +1100 2009  FOOBAR_03a_05_Enter_FOOBAR_Type                              10437.0
1254994729.28   1254994743.499          Thu Oct 08 20:38:49 +1100 2009  FOOBAR_03a_06_Search_for_Primary_Person                      14219.0
1254994748.093  1254994767.265          Thu Oct 08 20:39:08 +1100 2009  FOOBAR_03a_07_Associate_Primary_Person                       19172.0
1254994767.265  1254994780.796          Thu Oct 08 20:39:27 +1100 2009  FOOBAR_03a_08_Enter_Primary_Person_Address_Details           13531.0
1254994780.796  1254994818.765          Thu Oct 08 20:39:40 +1100 2009  FOOBAR_03a_09_Enter_Primary_Person_Doc_Details        37969.0
1254994818.765  1254994835.906          Thu Oct 08 20:40:18 +1100 2009  FOOBAR_03a_16_Add_PoC _Link                                     17141.0
1254994838.828  1254994843.515          Thu Oct 08 20:40:38 +1100 2009  FOOBAR_03a_17_Add_PoC                                            4687.0
1254994852.078  1254994855.469          Thu Oct 08 20:40:52 +1100 2009  FOOBAR_03a_18_Search_Agent                                       3391.0
1254994855.469  1254994859.203          Thu Oct 08 20:40:55 +1100 2009  FOOBAR_03a_19_View_Agent                                         3734.0
1254994863.953  1254994876.203          Thu Oct 08 20:41:03 +1100 2009  FOOBAR_03a_20_Associate_Agent                                   12250.0
1254994876.203  1254994879.484          Thu Oct 08 20:41:16 +1100 2009  FOOBAR_03a_21_Add_Payment_Link                                   3281.0
1254994894.094  1254994894.703          Thu Oct 08 20:41:34 +1100 2009  FOOBAR_03a_22_Record_Payment_Details                              609.0
1254995196.611  1254995196.611          Thu Oct 08 20:46:36 +1100 2009  SAP                                                                    0.0
1254995202.486  1254995258.517          Thu Oct 08 20:46:42 +1100 2009  FOOBAR_03a_25_ Run Validity Assessment                          56031.0
1254995267.736  1254995280.017          Thu Oct 08 20:47:47 +1100 2009  FOOBAR_03a_27_Record_Notes                                      12281.0
1254995280.017  1254995346.579          Thu Oct 08 20:48:00 +1100 2009  FOOBAR_03a_28_Save_And_Foobaz                                    66562.0</pre></div></div>

<p>Which gives you things like start and stop times, elapsed times and action names to help you debug things further down the track.</p>
<p>All up I think it&#8217;s a pretty neat solution for re-re-re-recording LoadRunner scripts (or your tool of choice) you inevitably face in fast changing environments. Whilst writing this post I had a script ticking away in the background recording some 3000+ LoadRunner events. YMMV.</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/watir-powered-loadrunner-scripts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Polling a Resource with Fibonacci Determined Sleep Intervals</title>
		<link>http://altentee.com/2009/polling-a-resource-with-fibonacci-determined-sleep-intervals/</link>
		<comments>http://altentee.com/2009/polling-a-resource-with-fibonacci-determined-sleep-intervals/#comments</comments>
		<pubDate>Wed, 23 Sep 2009 00:13:04 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2009/polling-a-resource-with-fibonacci-determined-sleep-intervals/</guid>
		<description><![CDATA[<p>In mathematics, Fibonacci numbers are the following sequence of numbers:
0, 1, 1, 2, 3, 5, 8, 13, &#8230;</p>
<p>By definition, the first two Fibonacci numbers are 0 and 1, and each remaining number is the sum of the previous two. This naturally occurring sequence is useful for determining the amount of time to sleep whenever you [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>In mathematics, Fibonacci numbers are the following sequence of numbers:<br />
0, 1, 1, 2, 3, 5, 8, 13, &#8230;</p>
<p>By definition, the first two <a href="http://en.wikipedia.org/wiki/Fibonacci_number"><strong>Fibonacci</strong></a> numbers are 0 and 1, and each remaining number is the sum of the previous two. This naturally occurring sequence is useful for determining the amount of time to sleep whenever you are polling a resource.</p></blockquote>
<p>I&#8217;m often required to poll a database resource in some sort of daemon. For example, check a table for some asynchronous tasks to complete. If you have a lot of threads polling this resource at quick intervals, the impact on the resource can be excessive/high. Rather than poll at a set interval, I use a Fibonacci sequence to determine what the next sleep interval will be. Following are code examples of this polling technique hosted on GitHub in my most commonly used programming languages&#8230;<br />
<span id="more-253"></span><br />
<a href="http://github.com/90kts/poll_resource/blob/master/poll_fibonacci.rb"><strong>Ruby</strong></a><br />
<a href="http://github.com/90kts/poll_resource/blob/master/poll_fibonacci.pl"><strong>Perl</strong></a><br />
<a href="http://github.com/90kts/poll_resource/blob/master/poll_fibonacci.php"><strong>PHP</strong></a></p>
<p>Essentially what each script does is the following &#8230;</p>
<p>Initialise a thread with a sleep interval of 5 seconds (or F5 in reference to the Fibonacci sequence number)</p>
<p>The thread will then:<br />
  1. Check if there is work to do by polling the resource<br />
  2. Complete any work and indicate if work has been done<br />
  3. If work has been done then next sleep interval will be 3 seconds (or F5-1)<br />
  4. If work has not been done then next sleep interval will be 8 seconds (or F5+1)<br />
  5. Sleep for the desired interval and loop</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/polling-a-resource-with-fibonacci-determined-sleep-intervals/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Framework for JMeter using GitHub and Ruby</title>
		<link>http://altentee.com/2009/a-framework-for-jmeter-using-github-and-ruby/</link>
		<comments>http://altentee.com/2009/a-framework-for-jmeter-using-github-and-ruby/#comments</comments>
		<pubDate>Fri, 18 Sep 2009 04:44:05 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[jmeter]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2009/a-framework-for-jmeter-using-github-and-ruby/</guid>
		<description><![CDATA[<p>Version control is not something you often associate with performance testing scripts. The reasons generally vary. A significant one is the lack of any version control support in commercial toolsets like LoadRunner. Another reason is the perceived short-term shelf life of test scripts. You tend to write them once and throw them away right?</p>
<p>If you [...]]]></description>
			<content:encoded><![CDATA[<p>Version control is not something you often associate with performance testing scripts. The reasons generally vary. A significant one is the lack of any version control support in commercial toolsets like LoadRunner. Another reason is the perceived short-term shelf life of test scripts. You tend to write them once and throw them away right?</p>
<p>If you work with more agile teams/developers you will probably start to require a lot of re-use out of your scripts, especially when the release cycle increases in terms of frequency. It starts to make sense to use version control and some form of scripting framework.</p>
<p>In this post I&#8217;m going to use JMeter as the tool of choice here and I&#8217;m going to re-introduce concepts which I normally force upon others whilst contracting. That is, use of Application Simulation Models (ASMs) to hep define the load and use of the Application Performance Index (Apdex) to help present results. I&#8217;m also going to use GitHub (or git) as my tool for maintaining version control and implementing a wiki as a dashboard replacement for other test management tools.<br />
<span id="more-246"></span></p>
<p>In short, I&#8217;m hosting version controlled scripts on GitHub. You can view my repository here:<br />
<a href="http://wiki.github.com/90kts/performance_test"><strong>http://wiki.github.com/90kts/performance_test</strong><br />
</a><br />
I&#8217;m using Google Documents to store my ASMs. You can see an example <a href="http://spreadsheets.google.com/ccc?key=0AuXn6ttUcRvbdERrd0lVWFNfLWJEc3RJdXVqenNTSVE&#038;hl=en"><strong>here</strong></a>.</p>
<p>I&#8217;m also using the Wiki functionality of GitHub plus some Ruby scripts as my test runners. In other words, a scripted version of a controller, driven by data from the ASMs.</p>
<p>GitHub can be quite useful. Not only can you version control all your scripts, you can also implement  concepts based around a &#8220;<a href="http://www.satisfice.com/presentations/dashboard.pdf"><strong>low-tech testing dashboard</strong></a>&#8221;  first explored by James Bach. The use of a wiki to support this was recently explored by Matthew at <a href="http://xndev.blogspot.com/2009/09/test-management-tools.html"><strong>Socialtext</strong></a>.  Coupled with that you also get an Issues database which is perfect for tracking those performance defects during test execution. Google Docs is also very useful in that it allows you to centrally store test artifacts like your ASMs which has plenty of <a href="http://roo.rubyforge.org/">neat APIs</a> for programatically accessing content. Start working more with GitHub and less with QualityCentre and watch your circle of geek friends change. <img src='http://altentee.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><strong>Dashboard</strong><br />
So my <a href="http://wiki.github.com/90kts/performance_test/dashboard"><strong>dashboard</strong></a> is really just a broad sweep of major system and application components that present some level of risk to application stability and performance. It&#8217;s represented in the GitHub wiki as follows:<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/09/dashboard1.png' title='dashboard 2'><img src='http://90kts.com/blog/wp-content/uploads/2009/09/dashboard1.png' alt='dashboard 2' /></a></p>
<p>Main elements are the areas I wish to test, the estimated effort required to script/prepare those areas, an indication of risk to production stability (carried out separately in risk assessments with appropriate technical/business teams), day to day comments on test readiness and a link to the online ASM. I use the keywords &#8220;run&#8221; or &#8220;draft&#8221; to distinguish between ASM status&#8217;. This helps the test runner determine which tests to execute.</p>
<p><strong>Test Runner</strong><br />
The <a href="http://github.com/90kts/performance_test/blob/master/scripts/test_runner.rb"><strong>test runner</strong></a> is a Ruby script which when executed, queries the Dashboard for ASMs to execute (based on the keyword &#8220;run&#8221;) then fetches the appropriate ASM via Google Documents to parse out relevant volumetrics for the test. Finally, it launches thread groups within JMeter to execute the test according to the ASM. Results are stored in the corresponding logs directory.</p>
<p><strong>Apdex</strong><br />
If you&#8217;d like to find out more about the Application Performance Index please see <a href="http://apdex.org/"><strong>here</strong></a>. I&#8217;ve found Apdex to be a very useful format to communicate application performance consistently to non-tech-heads. There&#8217;s plenty of room to geek out at low level later, but for a 20,000&#8242; view on things, Apdex is often a good start. I&#8217;ve implemented Apdex support for this framework using a <a href="http://github.com/90kts/performance_test/blob/master/scripts/apdex.rb"><strong>Ruby script</strong></a> to parse the results. The <a href="http://googlecharts.rubyforge.org/"><strong>Google chart API for Ruby</strong></a> is used to present sparklines. You can do this during or after a test run has complete. It basically picks up results from the logs directory and parses them against response time targets specified in the ASM. The output of the Apdex script is a html page which looks like this:<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/09/apdex.png' title='apdex ruby'><img src='http://90kts.com/blog/wp-content/uploads/2009/09/apdex.png' alt='apdex ruby' /></a></p>
<p><strong>Application Simulation Models</strong><br />
The <a href="http://spreadsheets.google.com/ccc?key=0AuXn6ttUcRvbdERrd0lVWFNfLWJEc3RJdXVqenNTSVE&#038;hl=en"><strong>ASM</strong></a> is really the brains behind the JMeter test plan. It looks like this:<br />
 <a href='http://90kts.com/blog/wp-content/uploads/2009/09/asm.png' title='ASM'><img src='http://90kts.com/blog/wp-content/uploads/2009/09/asm.thumbnail.png' alt='ASM' /></a><a href='http://90kts.com/blog/wp-content/uploads/2009/09/asm2.png' title='asm2'><img src='http://90kts.com/blog/wp-content/uploads/2009/09/asm2.thumbnail.png' alt='asm2' /></a></p>
<p>It has two worksheets. The ASM worksheet is intended for business stakeholders. It&#8217;s geared more towards their understanding. I encourage these groups to articulate load in terms of transaction distribution (how many and what types of transactions groups) and user distribution (who are your user groups and what do they consist of). The key metrics I get these groups to enter are highlighted in yellow. Things like different user groups, percentage breakdowns of transactions and transaction/concurrent user quantities. Have a play, it&#8217;s pretty easy to follow. Coincidentally in every contract I&#8217;ve worked, I make this a mandatory test artifact for both my testers and the teams they&#8217;ve engaged with. No ASM = No Performance test&#8230;</p>
<p>The Scenario worksheet is really just the reverse of the first. It breaks down all the metrics that the business have provided into a worksheet to help you plug figures into your test scenarios. It helps cut down user-errors when calculating transaction rates etc and makes it much easier to chop and change figures. Want to do a test run with less concurrent users or higher transaction throughput? Just muck around with the percentages in yellow. I&#8217;ve used this format for both LoadRunner and JMeter gigs, so the terminology is meant to be familiar to both those types of users.</p>
<p><strong>JMeter Test Plan</strong><br />
Through the beauty of JMeter -J command line parameters I&#8217;m able to pass all the relevant metrics from the ASM such as number of threads (vusers), duration, throughput, rampup and action(transaction) distribution percentages. I use this <a href="http://github.com/90kts/performance_test/blob/master/plans/template_load_test.jmx"><strong>template format</strong></a> quite often and have explained some of these concepts previously.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/09/jmeter_template.png' title='jmeter template'><img src='http://90kts.com/blog/wp-content/uploads/2009/09/jmeter_template.png' alt='jmeter template' /></a></p>
<p>The test plan gets the required parameters from the command line at run time. You can see the User Defined Variables look something like this:<br />
<code>DURATION = ${__P(duration,60) </code></p>
<p>Which basically sets the ${DURATION} JMeter variable based on the -Jduration command line variable, or defaults to 60 seconds if it is not passed. Other variables are also defined here and get loaded into the main Thread Group.</p>
<p>I use a Runtime Controller to control how long the test plan executes for. I also keep a separate Transaction Controller called Init to execute login actions etc or things I only want to execute once in the test plan.</p>
<p>Nested inside the Runtime Controller I use Throughput Controllers with percent executions tied to action percentages defined in the ASM. For example, action 1 might be a &#8220;view product&#8221; sequence of requests which I execute 50% of the time and so forth. Similar to weighted percentages for transaction blocks in LoadRunner. It is best to calculate these percentages using the Per User mode in JMeter for more accurate results.</p>
<p>Nested inside Throughput Controllers will be further Transaction Controllers, with Generate Parent Sample checked to enable similar functionality to transaction timers in LoadRunner around groups of requests.</p>
<p>The whole Thread Group has its throughput limited with a Constant Throughput Timer which basically tries to make all active threads in the thread group stay at a constant rate (defined by samples per minute). This eliminates the need to figure out pacing or sleep times as you might in LoadRunner.</p>
<p>The Summary Report and Gaussian Random Timers are just used for debugging so don&#8217;t normally include those in the final script&#8230;</p>
<p><strong>Git</strong><br />
Want to get started? Well first you will need a copy of a git client. Have a look at various how-to guides out there to get you started. I&#8217;ve found this <a href="http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html"><strong>site</strong></a> pretty useful for understanding and working with git basics. My public clone URL for all the code used in this post is available here:<br />
git://github.com/90kts/performance_test.git</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/a-framework-for-jmeter-using-github-and-ruby/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
