<?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/"
	>

<channel>
	<title>Agile Web Operations</title>
	<atom:link href="http://www.agileweboperations.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.agileweboperations.com</link>
	<description>Helping web developers and operations bridge the deployment gap</description>
	<pubDate>Fri, 03 Jul 2009 19:40:48 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<image>
<link>http://www.agileweboperations.com</link>
<url>http://www.agileweboperations.com/favicon.ico</url>
<title>Agile Web Operations</title>
</image>
		<item>
		<title>Monitoring OpenSolaris Zones with Nagios</title>
		<link>http://www.agileweboperations.com/monitoring-opensolaris-zones-with-nagios/</link>
		<comments>http://www.agileweboperations.com/monitoring-opensolaris-zones-with-nagios/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 19:24:22 +0000</pubDate>
		<dc:creator>Matthias Marschall</dc:creator>
		
		<category><![CDATA[Web Development & Operations]]></category>

		<category><![CDATA[monitoring]]></category>

		<category><![CDATA[nagios]]></category>

		<category><![CDATA[OpenSolaris]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1426</guid>
		<description><![CDATA[We&#8217;re running separate zones for web, app, and db servers. To be able to know the health of our application and our servers, we rely on pnp4nagios for graphing performance data like CPU utilization, memory usage, etc. Using OpenSolaris zones, there is only one OS kernel running. This is different in e.g. XEN, where every [...]


Related posts:<ul><li><a href='http://www.agileweboperations.com/monitoring-tools-essentials-munin-vs-nagios/' rel='bookmark' title='Permanent Link: Monitoring tools essentials: Munin vs. Nagios'>Monitoring tools essentials: Munin vs. Nagios</a></li><li><a href='http://www.agileweboperations.com/behavior-driven-ops-kanban-vs-scrum-and-a-new-upcoming-monitoring-and-trending-tool/' rel='bookmark' title='Permanent Link: Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool'>Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool</a></li><li><a href='http://www.agileweboperations.com/kent-langley-talks-about-joyent-their-new-accelerators-and-their-use-opensolaris/' rel='bookmark' title='Permanent Link: Kent Langley Talks About Joyent, Their New Accelerators And Their Use of Opensolaris'>Kent Langley Talks About Joyent, Their New Accelerators And Their Use of Opensolaris</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.agileweboperations.com/wp-content/uploads/2009/07/indexphp.png"><img src="http://www.agileweboperations.com/wp-content/uploads/2009/07/indexphp-300x104.png" alt="OpenSolaris Zone Memory pnp4nagios graph" title="OpenSolaris Zone Memory pnp4nagios graph" width="300" height="104" class="alignleft size-medium wp-image-1430" /></a>We&#8217;re running separate zones for web, app, and db servers. To be able to know the health of our application and our servers, we rely on<a href="http://www.pnp4nagios.org/pnp/start"> pnp4nagios</a> for graphing performance data like CPU utilization, memory usage, etc. Using OpenSolaris zones, there is only one OS kernel running. This is different in e.g. XEN, where every VM runs it&#8217;s own kernel. Such a &#8220;one kernel setup&#8221; has some important implications for monitoring: Within a zone, you see CPU utiliziation and memory usage of the whole box (the kernel) instead of what is used by the zone. None of the available nagios check scripts is able to report that data by zone.</p>
<h3>Nagios Plugin for monitoring OpenSolaris Zones CPU und MEM</h3>
<p><span id="more-1426"></span><br />
To get CPU and memory data by zone, there is <code>prstat -Z</code>. Executed from within the global zone it returns a list of all zones, their current memory and CPU utilization, etc.</p>
<pre>
ZONEID    NPROC  SWAP   RSS MEMORY      TIME  CPU ZONE
     3       34 2443M 2430M    15%   9:03:05 7.9% app
     4       19 2562M 2014M    12% 288:22:24 1.7% db
     0       51   85M   92M   0.6% 145:57:00 1.6% global
     2      143  483M  192M   1.2%   0:17:52 0.6% web
     1       19 3106M 3111M    19%   0:49:05 0.0% mem
</pre>
<p>Putting it into a script and passing an command line parameter for the zone name to it, the script can calculate a nagios status. The script returns that nagios status based on warning and critical thresholds, passed to the script together with nagios performance data.</p>
<h3>prstat -Z needs to run within the global zone</h3>
<p>Usually, our nagios server calls nagios check scripts, which need to run locally on the monitored box, via SSH. All our command definitions use $HOSTADDRESS$ as the target host for the SSH connection. $HOSTADDRESS$ resovles to the host under test during a nagios check run. But <code>prstat -Z</code> needs to run within the global zone. To deal with that I added the IP-address of the global zone as a parameter to the nagios check call:</p>
<pre>
check_command check_by_ssh_zone_mem!4000!5000!app2!5120!10.0.0.1
</pre>
<p>In my command definition I changed the SSH target from $HOSTADDRESS$ to $ARG5$ making the check_by_ssh script connect to the global zone instead of the host under test.</p>
<p>Now we get nice CPU and MEM usage graphs for our OpenSolaris zones. As soon as I&#8217;ll have added documentation to my nagios check scripts, I&#8217;ll publish them on <a href="http://www.monitoringexchange.org/cgi-bin/page.cgi?d=1">MonitoringExchange</a> for everyone to scrunitize and maybe even use.</p>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/monitoring-tools-essentials-munin-vs-nagios/' rel='bookmark' title='Permanent Link: Monitoring tools essentials: Munin vs. Nagios'>Monitoring tools essentials: Munin vs. Nagios</a></li><li><a href='http://www.agileweboperations.com/behavior-driven-ops-kanban-vs-scrum-and-a-new-upcoming-monitoring-and-trending-tool/' rel='bookmark' title='Permanent Link: Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool'>Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool</a></li><li><a href='http://www.agileweboperations.com/kent-langley-talks-about-joyent-their-new-accelerators-and-their-use-opensolaris/' rel='bookmark' title='Permanent Link: Kent Langley Talks About Joyent, Their New Accelerators And Their Use of Opensolaris'>Kent Langley Talks About Joyent, Their New Accelerators And Their Use of Opensolaris</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/monitoring-opensolaris-zones-with-nagios/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool</title>
		<link>http://www.agileweboperations.com/behavior-driven-ops-kanban-vs-scrum-and-a-new-upcoming-monitoring-and-trending-tool/</link>
		<comments>http://www.agileweboperations.com/behavior-driven-ops-kanban-vs-scrum-and-a-new-upcoming-monitoring-and-trending-tool/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 20:41:58 +0000</pubDate>
		<dc:creator>Matthias Marschall</dc:creator>
		
		<category><![CDATA[Agile Methodologies]]></category>

		<category><![CDATA[Web Development & Operations]]></category>

		<category><![CDATA[agile]]></category>

		<category><![CDATA[BDD]]></category>

		<category><![CDATA[cucumber]]></category>

		<category><![CDATA[kanban]]></category>

		<category><![CDATA[monitoring]]></category>

		<category><![CDATA[nagios]]></category>

		<category><![CDATA[operations]]></category>

		<category><![CDATA[scrum]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1409</guid>
		<description><![CDATA[
Testing Dash Metrics with Cucumber (Bradley Taylor) - A short article showing off a Cucumber feature for monitoring with Nagios.
Kanban vs. Scrum (Henrik Kniberg) - A great, 26 page long PDF about the similarities and differences between Scrum and Kanban. Absolutely worth reading!
Reconnoiter (Theo Schlossnagle) - Theo and his OmniTI Labs are working on a [...]


Related posts:<ul><li><a href='http://www.agileweboperations.com/monitoring-tools-essentials-munin-vs-nagios/' rel='bookmark' title='Permanent Link: Monitoring tools essentials: Munin vs. Nagios'>Monitoring tools essentials: Munin vs. Nagios</a></li><li><a href='http://www.agileweboperations.com/acceptance-testing-with-cucumber/' rel='bookmark' title='Permanent Link: Acceptance Testing with Cucumber'>Acceptance Testing with Cucumber</a></li><li><a href='http://www.agileweboperations.com/webrat-automated-acceptance-testing-with-rspec-or-cucumber/' rel='bookmark' title='Permanent Link: webrat: Automated Acceptance Testing with RSpec or Cucumber'>webrat: Automated Acceptance Testing with RSpec or Cucumber</a></li></ul>]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://bradley.is/post/82649218/testing-dash-metrics-with-cucumber">Testing Dash Metrics with Cucumber</a> (Bradley Taylor) - A short article showing off a Cucumber feature for monitoring with Nagios.</li>
<li><a href="http://www.crisp.se/henrik.kniberg/Kanban-vs-Scrum.pdf">Kanban vs. Scrum</a> (Henrik Kniberg) - A great, 26 page long PDF about the similarities and differences between Scrum and Kanban. Absolutely worth reading!</li>
<li><a href="http://lethargy.org/~jesus/archives/121-Reconnoiter-and-another-platform.html">Reconnoiter</a> (Theo Schlossnagle) - Theo and his OmniTI Labs are working on a new monitoring and trending application - a combination of Nagios, Cacti and the like with the goal to ease administration and scale efficiently. No releases yet but looks promising.</li>
</ul>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/monitoring-tools-essentials-munin-vs-nagios/' rel='bookmark' title='Permanent Link: Monitoring tools essentials: Munin vs. Nagios'>Monitoring tools essentials: Munin vs. Nagios</a></li><li><a href='http://www.agileweboperations.com/acceptance-testing-with-cucumber/' rel='bookmark' title='Permanent Link: Acceptance Testing with Cucumber'>Acceptance Testing with Cucumber</a></li><li><a href='http://www.agileweboperations.com/webrat-automated-acceptance-testing-with-rspec-or-cucumber/' rel='bookmark' title='Permanent Link: webrat: Automated Acceptance Testing with RSpec or Cucumber'>webrat: Automated Acceptance Testing with RSpec or Cucumber</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/behavior-driven-ops-kanban-vs-scrum-and-a-new-upcoming-monitoring-and-trending-tool/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Setting up a test database on a ruby on rails continuous integration server using SQL instead of schema.rb</title>
		<link>http://www.agileweboperations.com/setting-up-a-test-database-on-a-ruby-on-rails-continuous-integration-server-using-sql-instead-of-schemarb/</link>
		<comments>http://www.agileweboperations.com/setting-up-a-test-database-on-a-ruby-on-rails-continuous-integration-server-using-sql-instead-of-schemarb/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 20:46:36 +0000</pubDate>
		<dc:creator>Matthias Marschall</dc:creator>
		
		<category><![CDATA[Web Development & Operations]]></category>

		<category><![CDATA[continuous integration]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1339</guid>
		<description><![CDATA[For developing our Ruby on Rails based web site, we usually take regular SQL dumps from our production servers (of course, anonymizing sensitive customer data along the way). Always having a fresh dump allows us to be on the safe side when writing database migrations. Having an up to date development database enables us to [...]


Related posts:<ul><li><a href='http://www.agileweboperations.com/seed-data-in-ruby-on-rails/' rel='bookmark' title='Permanent Link: Seed Data In Ruby On Rails'>Seed Data In Ruby On Rails</a></li><li><a href='http://www.agileweboperations.com/gloc-validation-problems-after-rails-21-upgrade/' rel='bookmark' title='Permanent Link: GLoc Validation Problems After Rails 2.1 Upgrade'>GLoc Validation Problems After Rails 2.1 Upgrade</a></li><li><a href='http://www.agileweboperations.com/setup-ruby-rails-project-using-lighthouse-api-activeresource/' rel='bookmark' title='Permanent Link: Setup a Ruby on Rails Project Using the Lighthouse API With ActiveResource'>Setup a Ruby on Rails Project Using the Lighthouse API With ActiveResource</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p>For developing our Ruby on Rails based web site, we usually take regular SQL dumps from our production servers (of course, anonymizing sensitive customer data along the way). Always having a <em>fresh</em> dump allows us to be on the safe side when writing database migrations. Having an up to date development database enables us to run our test suite as well; it&#8217;s just a matter of <code>rake db:test:prepare</code> to get our test database up-to-date. So far, so good.<br />
<span id="more-1339"></span><br />
Due to our use of some MySQL specific stuff (namely full-text-indices), which are not supported by the database agnostic schema.rb, we&#8217;re using <code>config.active_record.schema_format = :sql</code >. This makes <code>rake db:test:prepare</code> use <code>db:test:clone_structure</code> instead of <code>db:test:load</code>. Unfortunately, <code>db:test:clone_structure</code> <em>always</em> calls <code>db:structure:dump</code>, which tries to dump the <em>development</em> database structure to an SQL file. This is ok on a developer&#8217;s box but we ran into trouble on our continuous integration server.</p>
<p>We don&#8217;t want to setup a development environment on our CI server (which requires loading an anonymized production dump - quite a beast). It&#8217;s enough for us to have a test environment there, using a checked out <code>development_structure.sql</code> (created on a development box and checked into version control) to create the test database. Unfortunately, the rake tasks provided by rails do not cover this scenario.</p>
<p>So, we simply came up with the following addition to rails&#8217; set of rake tasks:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">namespace <span style="color:#ff3333; font-weight:bold;">:db</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  namespace <span style="color:#ff3333; font-weight:bold;">:test</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    desc <span style="color:#996600;">&quot;Recreate the test database from an existing db/development_structure.sql dump file&quot;</span>
    task <span style="color:#ff3333; font-weight:bold;">:load_structure</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">&quot;db:test:purge&quot;</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">establish_connection</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:test</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">connection</span>.<span style="color:#9900CC;">execute</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'SET foreign_key_checks = 0'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC00FF; font-weight:bold;">IO</span>.<span style="color:#CC0066; font-weight:bold;">readlines</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">join</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;nn&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>table<span style="color:#006600; font-weight:bold;">|</span>
        <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">connection</span>.<span style="color:#9900CC;">execute</span><span style="color:#006600; font-weight:bold;">&#40;</span>table<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p><code>rake db:test:load_structure</code> reads the checked out <code>development_structure.sql</code> and applies it to the test database (which it recreates first by defining <code>db:test:purge</code> as a pre-requisite). That&#8217;s all we need to have a fully up-to-date test database on our CI server! No need to worry about creating a full development environment there just to be able to run migrations and dump the updated schema prior to setting up the test database.</p>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/seed-data-in-ruby-on-rails/' rel='bookmark' title='Permanent Link: Seed Data In Ruby On Rails'>Seed Data In Ruby On Rails</a></li><li><a href='http://www.agileweboperations.com/gloc-validation-problems-after-rails-21-upgrade/' rel='bookmark' title='Permanent Link: GLoc Validation Problems After Rails 2.1 Upgrade'>GLoc Validation Problems After Rails 2.1 Upgrade</a></li><li><a href='http://www.agileweboperations.com/setup-ruby-rails-project-using-lighthouse-api-activeresource/' rel='bookmark' title='Permanent Link: Setup a Ruby on Rails Project Using the Lighthouse API With ActiveResource'>Setup a Ruby on Rails Project Using the Lighthouse API With ActiveResource</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/setting-up-a-test-database-on-a-ruby-on-rails-continuous-integration-server-using-sql-instead-of-schemarb/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Too Busy to Blog</title>
		<link>http://www.agileweboperations.com/too-busy-to-blog/</link>
		<comments>http://www.agileweboperations.com/too-busy-to-blog/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 07:41:51 +0000</pubDate>
		<dc:creator>Dan Ackerson</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1416</guid>
		<description><![CDATA[I&#8217;ve been busier than a one-legged man in an ass-kicking contest the past few weeks. And because of this I haven&#8217;t been keeping up with my weekly posts. But yesterday, after getting through the guilt trip, I realized that I was missing more than just blogging. I was missing my weekly retrospectives and thereby losing [...]


Related posts:<ul><li><a href='http://www.agileweboperations.com/stop-being-busy-get-productive/' rel='bookmark' title='Permanent Link: Stop Being Busy. Get Productive!'>Stop Being Busy. Get Productive!</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been busier than a one-legged man in an ass-kicking contest the past few weeks. And because of this I haven&#8217;t been keeping up with my weekly posts. But yesterday, after getting through the guilt trip, I realized that I was missing more than just blogging. I was missing my weekly retrospectives and thereby losing focus of my priorities. Currently, I am an &#8220;Army of One&#8221; so the only retrospective I&#8217;ve been conducting is with me, myself and you - the reader. </p>
<p>Not writing about and contemplating my experiences, successes and failures from the week&#8217;s work meant I wasn&#8217;t improving, wasn&#8217;t honing my focus. Last week, I had a velocity of 0. For the first time in over six months, I literally delivered no customer value in my weekly sprint. And I chalk it up to not blogging - or at least not holding my strange sort of online weekly retrospective.<br />
<span id="more-1416"></span><br />
Being too busy to hold retrospectives can be dangerous especially if you&#8217;re working alone. It&#8217;s too easy (and ofttimes down right seductive) to just grab the next story and jump in head first, finishing chores left and right and feeling good about your progress. Luckily, however, I&#8217;m religious about tracking and sharing my work with <a href="http://www.pivotaltracker.com/">Pivotal Tracker</a> so at least I knew I missed out on doing some for our users last week.</p>
<p>So, what the hell have I been working on? Setting up a new server to host our relaunched portal and putting the finishing touches on our corporate blog. But, wait, why isn&#8217;t this customer value? First of all, customers don&#8217;t care about how your Nagios install interfaces with Munin to collect server metrics. And while CSS often means the difference between a &#8220;ho-hum&#8221; site and &#8220;nice&#8221;, it&#8217;s definitely not the reason why users will read your content or yawn and click away.</p>
<p>What&#8217;s been keeping you from delivering customer value? Are you honest with yourself, your company and your users about delivering real user value? </p>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/stop-being-busy-get-productive/' rel='bookmark' title='Permanent Link: Stop Being Busy. Get Productive!'>Stop Being Busy. Get Productive!</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/too-busy-to-blog/feed/</wfw:commentRss>
		</item>
		<item>
		<title>webrat: Automated Acceptance Testing with RSpec or Cucumber</title>
		<link>http://www.agileweboperations.com/webrat-automated-acceptance-testing-with-rspec-or-cucumber/</link>
		<comments>http://www.agileweboperations.com/webrat-automated-acceptance-testing-with-rspec-or-cucumber/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 20:14:56 +0000</pubDate>
		<dc:creator>Matthias Marschall</dc:creator>
		
		<category><![CDATA[Web Development & Operations]]></category>

		<category><![CDATA[acceptance testing]]></category>

		<category><![CDATA[cucumber]]></category>

		<category><![CDATA[RSpec]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[testing]]></category>

		<category><![CDATA[webrat]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1401</guid>
		<description><![CDATA[Recently, I was looking deeper into how we could add some automated acceptance tests to our Ruby on Rails based website. We&#8217;re using RSpec since quite a while now for TDD, but doing some high level acceptance tests was not on our agenda so far.
DRY Cucumber Scenarios
The new cool kid on the block is Cucumber. [...]


Related posts:<ul><li><a href='http://www.agileweboperations.com/acceptance-testing-with-cucumber/' rel='bookmark' title='Permanent Link: Acceptance Testing with Cucumber'>Acceptance Testing with Cucumber</a></li><li><a href='http://www.agileweboperations.com/behavior-driven-ops-kanban-vs-scrum-and-a-new-upcoming-monitoring-and-trending-tool/' rel='bookmark' title='Permanent Link: Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool'>Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p>Recently, I was looking deeper into how we could add some automated acceptance tests to our Ruby on Rails based website. We&#8217;re using RSpec since quite a while now for TDD, but doing some high level acceptance tests was not on our agenda so far.</p>
<h3>DRY Cucumber Scenarios</h3>
<p>The new cool kid on the block is <a href="http://cukes.info/">Cucumber</a>. One of its main features is that you can describe acceptance tests in nearly plain English (or any other language) simplifying discussions with the product managers and other, non-technical stake holders. I&#8217;m really impressed by the ease, with which you can describe DRY scenarios like our login feature:<br />
<span id="more-1401"></span></p>
<pre>
Feature Login
  In order to be able to contribute
  users
  want to login

  Background:
    Given the user "kanban" exists
    And I am logged out
    And I am on the login page

  Scenario: Login a with valid user
    When I fill in "Benutzername" with "auser"
    And I fill in "Passwort" with "secret"
    And I press "Einloggen"
    Then I should see "Meine Seite"
    And I should see "Neuigkeiten auf meiner Seite"

  Scenario Outline: Login with invalid credentials
    When I fill in "Benutzername" with "< user_name >"
    And I fill in "Passwort" with "< password >"
    And I press "Einloggen"
    Then I should see "Einloggen"
    And I should see "Der Benutzername oder das Passwort stimmt nicht"

    Examples:
      |user_name|password|
      |auser|bla|
      |bla|secret|
      |bla|bla|
</pre>
<p><code>Background</code>, <code>Scenario Outline</code> and <code>Example</code> are the keywords enabling DRY descriptions.</p>
<h3>Hooking Scenrios to your app using webrat</h3>
<p>As I described in my previous post about <a href="http://www.agileweboperations.com/acceptance-testing-with-cucumber/">Acceptance Testing with Cucumber</a>, Cucumber comes with a set of pre-defined steps for webrat. So the steps are usually single line calls to webrat&#8217;s API:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">When</span> <span style="color:#006600; font-weight:bold;">/</span>^I <span style="color:#CC0066; font-weight:bold;">open</span> <span style="color:#006600; font-weight:bold;">&#40;</span>.<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span>$<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>url<span style="color:#006600; font-weight:bold;">|</span>
  visit url
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Acceptance Testing for a pure technical team</h3>
<p>So far, so good. Cucumber works great and has a very descriptive language perfectly suited for talking to non-technical folks. In our team, the situation is such that we hardly have to communicate in such great detail with our CEO - he&#8217;s mainly interested in the rough workings of a feature, but not in the details (he has other things to worry about <img src='http://www.agileweboperations.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ). As the product development team only consists of three tech guys, we wondered whether it&#8217;s necessary to have the English language abstraction. Wouldn&#8217;t it be nicer just to use RSpec with Cucumber to make it immediately obvious to technical folks, what the test <em>really</em> does (instead of <em>hiding</em> the details in step descriptions?</p>
<p>To be honest, I was not sure whether it was a good idea to go from Cucumber to RSpec. I feared that the tests would get cluttered by syntax and be much longer (and harder to read) than the Cucumber features. But, I gave it a try. And I was surprised. See for yourself - the same feature side by side as RSpec description and Cucumber feature:<br />
<a href="http://www.agileweboperations.com/wp-content/uploads/2009/06/bild-11.gif"><img src="http://www.agileweboperations.com/wp-content/uploads/2009/06/bild-11-1024x435.gif" alt="RSpec vs. Cucumber" title="RSpec vs. Cucumber" width="1024" height="435" class="aligncenter size-large wp-image-1404" /></a></p>
<p>Surprisingly enough, re-writing the feature as RSpec description does not bloat it. In fact, for a tech guy, it is easier to read than the feature as you see <em>exactly</em> what is happening right away. Additionally, you&#8217;ve got full Editor/IDE support for writing specs.</p>
<h3>RSpec vs Cucumber</h3>
<p>Cucumber is great. If you talk in detail about features with non-technical folks, it is the way to go. If you do not have to bridge such a gap between tech and non-tech  guys, you might be better off using webrat directly from within your specs. It removes one layer of indirection and doesn&#8217;t really make things worse to read, if you adapt best practices for structuring your specs from cucumber (like using examples and well named helpers).</p>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/acceptance-testing-with-cucumber/' rel='bookmark' title='Permanent Link: Acceptance Testing with Cucumber'>Acceptance Testing with Cucumber</a></li><li><a href='http://www.agileweboperations.com/behavior-driven-ops-kanban-vs-scrum-and-a-new-upcoming-monitoring-and-trending-tool/' rel='bookmark' title='Permanent Link: Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool'>Behavior Driven Ops, Kanban vs. Scrum and a new upcoming Monitoring and Trending Tool</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/webrat-automated-acceptance-testing-with-rspec-or-cucumber/feed/</wfw:commentRss>
		</item>
		<item>
		<title>1st Birthday: Best of Agile Web Operations</title>
		<link>http://www.agileweboperations.com/1st-birthday-best-of-agile-web-operations/</link>
		<comments>http://www.agileweboperations.com/1st-birthday-best-of-agile-web-operations/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 20:37:27 +0000</pubDate>
		<dc:creator>Matthias Marschall</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1383</guid>
		<description><![CDATA[It&#8217;s time to say &#8220;Thank you&#8221; to all of you, our loyal readers. Thanks for reading, commenting and subscribing to our posts for exactly one year now. That&#8217;s right, Agile Web Operations is now one year old. I can hardly put into words how great it is to have you with us!
103 posts and 113 [...]


Related posts:<ul><li><a href='http://www.agileweboperations.com/improving-operations-with-agile/' rel='bookmark' title='Permanent Link: Improving Operations with Agile'>Improving Operations with Agile</a></li><li><a href='http://www.agileweboperations.com/test-first-in-operations-at-the-build-doctor/' rel='bookmark' title='Permanent Link: Test First in Operations at The Build Doctor'>Test First in Operations at The Build Doctor</a></li><li><a href='http://www.agileweboperations.com/four-agile-posts-everyone-should-read/' rel='bookmark' title='Permanent Link: Four Agile Posts Everyone Should Read'>Four Agile Posts Everyone Should Read</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/yogi/147660382/"><img alt="" src="http://farm1.static.flickr.com/46/147660382_5c2b865771_m.jpg" class="alignleft" width="240" height="160" /></a>It&#8217;s time to say <strong>&#8220;Thank you&#8221;</strong> to all of you, our loyal readers. Thanks for reading, commenting and subscribing to our posts for exactly one year now. That&#8217;s right, Agile Web Operations is now one year old. I can hardly put into words how great it is to have you with us!</p>
<p>103 posts and 113 comments. That&#8217;s the result of our first year. And, exactly 200 of you have subscribed to our RSS feed - an excellent choice. For all of you who joined recently (and to remind you veterans), check out the five most read posts:</p>
<ol>
<li><a href="http://www.agileweboperations.com/puppet-or-capistrano-use-the-right-tool-for-the-job/">Puppet or Capistrano - Use the Right Tool for the Job</a> (Guest post by <a href="http://twitter.com/littleidea">Andrew Shafer</a>)</li>
<li><a href="http://www.agileweboperations.com/puppet-vs-capistrano-short-comparison/">Puppet vs. Capistrano - a short comparison</a></li>
<li><a href="http://www.agileweboperations.com/system-configurations-code-revisions-continuous-integration-ftw/">System Configurations + Code Revisions = Continuous Integration FTW</a> (Guest post by <a href="http://twitter.com/patrickdebois">Patrick Debois</a>)</li>
<li><a href="http://www.agileweboperations.com/thoughtworks-mingle-vs-pivotal-labs-tracker/">Thoughtworks Mingle vs. Pivotal Labs Tracker</a></li>
<li><a href="http://www.agileweboperations.com/agile-tool-vendors-please-dont-try-to-manage-complexity-simplify-my-life/">Agile Tool Vendors: Please don’t try to manage complexity - simplify my life!</a></li>
</ol>
<p>And don&#8217;t miss out on our three most commented posts:</p>
<ul>
<li><a href="http://www.agileweboperations.com/agile-quo-vadis/">Agile on steroids</a></li>
<li><a href="http://www.agileweboperations.com/configuration-management-remixed-introducing-carpet/">Configuration Management remixed: Introducing Carpet</a></li>
<li><a href="http://www.agileweboperations.com/visible-ops-rolling-out-change-management/">Visible Ops: Rolling Out Change Management</a>
</ul>
<p>I hope you enjoy reading Agile Web Operations as much as we do writing it. Keep the comments flowing and don&#8217;t forget to tell your friends!</p>
<p>We&#8217;re looking forward to the coming years of Agile Web Operations.</p>
<p>Sincerely yours,</p>
<p>Dan &#038; Matthias</p>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/improving-operations-with-agile/' rel='bookmark' title='Permanent Link: Improving Operations with Agile'>Improving Operations with Agile</a></li><li><a href='http://www.agileweboperations.com/test-first-in-operations-at-the-build-doctor/' rel='bookmark' title='Permanent Link: Test First in Operations at The Build Doctor'>Test First in Operations at The Build Doctor</a></li><li><a href='http://www.agileweboperations.com/four-agile-posts-everyone-should-read/' rel='bookmark' title='Permanent Link: Four Agile Posts Everyone Should Read'>Four Agile Posts Everyone Should Read</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/1st-birthday-best-of-agile-web-operations/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Seed Data In Ruby On Rails</title>
		<link>http://www.agileweboperations.com/seed-data-in-ruby-on-rails/</link>
		<comments>http://www.agileweboperations.com/seed-data-in-ruby-on-rails/#comments</comments>
		<pubDate>Thu, 28 May 2009 20:45:19 +0000</pubDate>
		<dc:creator>Matthias Marschall</dc:creator>
		
		<category><![CDATA[Web Development & Operations]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1373</guid>
		<description><![CDATA[To run automated tests for your Ruby on Rails webapp, not only do you need your latest database structure deployed to the test database (created by rake db:test:prepare), but you also need some seed data for lookup tables, e.g. like zip codes.
Common approaches like adding seed data through rails migrations are discouraged, and plugins like [...]


Related posts:<ul><li><a href='http://www.agileweboperations.com/setting-up-a-test-database-on-a-ruby-on-rails-continuous-integration-server-using-sql-instead-of-schemarb/' rel='bookmark' title='Permanent Link: Setting up a test database on a ruby on rails continuous integration server using SQL instead of schema.rb'>Setting up a test database on a ruby on rails continuous integration server using SQL instead of schema.rb</a></li><li><a href='http://www.agileweboperations.com/setup-ruby-rails-project-using-lighthouse-api-activeresource/' rel='bookmark' title='Permanent Link: Setup a Ruby on Rails Project Using the Lighthouse API With ActiveResource'>Setup a Ruby on Rails Project Using the Lighthouse API With ActiveResource</a></li><li><a href='http://www.agileweboperations.com/gloc-validation-problems-after-rails-21-upgrade/' rel='bookmark' title='Permanent Link: GLoc Validation Problems After Rails 2.1 Upgrade'>GLoc Validation Problems After Rails 2.1 Upgrade</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p><img src="http://farm4.static.flickr.com/3200/2908703594_17861e6c09_m.jpg" title="Apple chockfull of seeds, II - by lepiaf.geo" border="0" class="alignright"/>To run automated tests for your Ruby on Rails webapp, not only do you need your latest database structure deployed to the test database (created by <code>rake db:test:prepare</code>), but you also need some seed data for lookup tables, e.g. like zip codes.</p>
<p>Common approaches like adding seed data through rails migrations are discouraged, and plugins like <a href="http://github.com/mbleigh/seed-fu/tree/master">seed_fu</a> only work for small amounts of seed data. In seed_fu, you can specify a <code>seed</code> method for your ActiveRecord models like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">User.<span style="color:#9900CC;">seed</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:login</span>, <span style="color:#ff3333; font-weight:bold;">:email</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>s<span style="color:#006600; font-weight:bold;">|</span>
      s.<span style="color:#9900CC;">login</span> = <span style="color:#996600;">&quot;bob&quot;</span>
      s.<span style="color:#9900CC;">email</span> = <span style="color:#996600;">&quot;bob@bobson.com&quot;</span>
      s.<span style="color:#9900CC;">first_name</span> = <span style="color:#996600;">&quot;Bob&quot;</span>
      s.<span style="color:#9900CC;">last_name</span> = <span style="color:#996600;">&quot;Bobson&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Running the <code>rake db:seed</code> task provided by seed_fu will add all defined models to your test database. </p>
<p>DHH has even standardized a way to <a href="http://github.com/rails/rails/commit/4932f7b38f72104819022abca0c952ba6f9888cb">load seed data for Rails 3</a>, making the <code>rake db:seed</code> task part of rails and setting up a file called <code>db/seeds.rb</code> for maintaining your seeding code. Using  that file, you can load your seed data however you see fit, e.g. seed_fu.</p>
<h3>How to Deal With Big Amounts of Seed Data</h3>
<p><span id="more-1373"></span><br />
So far, so good. There are ways to load seed data into your rails test database using Ruby code. But what if, like in our case, you have to seed more than 60,000 Points of Interest and over 16,000 cars? We definitely don&#8217;t want to write Ruby code for each of them. The only sane way of handling such amounts of data are database dumps. So I added my own <code>rake db:seed:dump</code> and <code>rake db:seed:load</code> tasks to our Rails 2.3.2 application. As soon as we move to Rails 3, we can call the load task from within <code>db/seeds.rb</code>.</p>
<p>Short and sweet (and completely MySQL specific and dependent on MySQL living in your path <img src='http://www.agileweboperations.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ) here are my two rake tasks:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">namespace <span style="color:#ff3333; font-weight:bold;">:db</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  namespace <span style="color:#ff3333; font-weight:bold;">:seed</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'db/seed_tables'</span>
&nbsp;
    desc <span style="color:#996600;">&quot;dump the tables holding seed data to db/RAILS_ENV_seed.sql. SEED_TABLES need to be defined in config/environment.rb!!!&quot;</span>
    task <span style="color:#ff3333; font-weight:bold;">:dump</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:environment</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      config = <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">configurations</span><span style="color:#006600; font-weight:bold;">&#91;</span>RAILS_ENV<span style="color:#006600; font-weight:bold;">&#93;</span>
      dump_cmd = <span style="color:#996600;">&quot;mysqldump --user=#{config['username']} --password=#{config['password']} #{config['database']} #{SEED_TABLES.join(&quot;</span> <span style="color:#996600;">&quot;)} &gt; db/#{RAILS_ENV}_seed.sql&quot;</span>
      <span style="color:#CC0066; font-weight:bold;">system</span><span style="color:#006600; font-weight:bold;">&#40;</span>dump_cmd<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    desc <span style="color:#996600;">&quot;load the dumped seed data from db/development_seed.sql into the test database&quot;</span>
    task <span style="color:#ff3333; font-weight:bold;">:load</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:environment</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      config = <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">configurations</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'test'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#CC0066; font-weight:bold;">system</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;mysql --user=#{config['username']} --password=#{config['password']} #{config['database']} &lt; db/#{RAILS_ENV}_seed.sql&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
     <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Note that I use a file called <code>db/seed_tables.rb</code> to define, which tables shall be dumped. It just holds an array of table names like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">SEED_TABLES = <span style="color:#006600; font-weight:bold;">&#91;</span>
  <span style="color:#996600;">&quot;auxilary_services&quot;</span>,
  <span style="color:#996600;">&quot;background_informations&quot;</span>,
  <span style="color:#996600;">&quot;pois&quot;</span>
<span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>

<p>Using two basic rake tasks and database dumps eases the pain of handling test data for us. How do you manage your test data? Let us know in the comments!</p>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/setting-up-a-test-database-on-a-ruby-on-rails-continuous-integration-server-using-sql-instead-of-schemarb/' rel='bookmark' title='Permanent Link: Setting up a test database on a ruby on rails continuous integration server using SQL instead of schema.rb'>Setting up a test database on a ruby on rails continuous integration server using SQL instead of schema.rb</a></li><li><a href='http://www.agileweboperations.com/setup-ruby-rails-project-using-lighthouse-api-activeresource/' rel='bookmark' title='Permanent Link: Setup a Ruby on Rails Project Using the Lighthouse API With ActiveResource'>Setup a Ruby on Rails Project Using the Lighthouse API With ActiveResource</a></li><li><a href='http://www.agileweboperations.com/gloc-validation-problems-after-rails-21-upgrade/' rel='bookmark' title='Permanent Link: GLoc Validation Problems After Rails 2.1 Upgrade'>GLoc Validation Problems After Rails 2.1 Upgrade</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/seed-data-in-ruby-on-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using SiteSucker For Testing Redirects</title>
		<link>http://www.agileweboperations.com/using-sitesucker-for-testing-redirects/</link>
		<comments>http://www.agileweboperations.com/using-sitesucker-for-testing-redirects/#comments</comments>
		<pubDate>Sun, 24 May 2009 07:27:01 +0000</pubDate>
		<dc:creator>Dan Ackerson</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1353</guid>
		<description><![CDATA[
My boss threw down the gauntlet Monday morning during our weekly meeting. In relaunching one of our decade old platforms, we couldn&#8217;t afford to get bashed by fickle finger of Google Search Results and I needed to take extra care in ensuring all redirects were properly made. With over twenty thousand pages, it was no [...]


Related posts:<ul><li><a href='http://www.agileweboperations.com/acceptance-testing-with-cucumber/' rel='bookmark' title='Permanent Link: Acceptance Testing with Cucumber'>Acceptance Testing with Cucumber</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p><a href="ttp://www.flickr.com/photos/coda/240920814/"><img alt="" src="http://farm1.static.flickr.com/89/240920814_5e03d0ea0f_m.jpg" class="alignright" width="240" height="180" /></a><br />
My boss threw down the gauntlet Monday morning during our weekly meeting. In relaunching one of our decade old platforms, we couldn&#8217;t afford to get bashed by fickle finger of Google Search Results and I needed to take extra care in ensuring all redirects were properly made. With over twenty thousand pages, it was no small task and I struggled finding a way to automate it.</p>
<p>Ultimately, I had to make a compromise between feasibility and correctness, but I&#8217;m pretty satisified with the results. In fact, <a href="http://www.sitesucker.us/home.html">SiteSucker</a> was able to confirm that, besides images, we did manage a 100% conversion for all the existing urls.<br />
<span id="more-1353"></span></p>
<h3>Google Analytics &#038; Full Realization</h3>
<p>At first, I spent about a day going through the top 1000 URLs according to the Google Analytics tracker. This was horribly redundant, mind-numbing work but I didn&#8217;t see a way to export all 5 MILLION URLs that Google Analytics had on on record for the last month.<br />
<img src="http://www.agileweboperations.com/wp-content/uploads/2009/05/ga-hell1.png" alt="ga-hell1" title="ga-hell1" width="562" height="167" class="aligncenter size-full wp-image-1359" /></p>
<p>I calculated at the rate I needed to go through the top 1000, I&#8217;d need almost 7 <strong>years</strong> to double check the rest. And, of course, I knew we didn&#8217;t have that many valid pages in our site.</p>
<h3>Site Sucker to the Rescue</h3>
<p>I&#8217;d used SiteSucker a few times in recent months to double check the health of our site&#8217;s link structure. It&#8217;s extremely fast and the user interface is very lean (making use of Mac OS&#8217;s Console logging application). What I wondered was how I could execute a web crawl not from a site, but from a saved file? Turns out, it&#8217;s very easy!</p>
<p>First, ensure the settings of SiteSucker to log the download history (and save that log):<br />
<img src="http://www.agileweboperations.com/wp-content/uploads/2009/05/gpp-settings.png" alt="gpp-settings" title="gpp-settings" width="638" height="287" class="aligncenter size-full wp-image-1360" /></p>
<p>Then, enter the original sitename in the Web URL input and hit enter. You&#8217;re off to the races!<br />
<img src="http://www.agileweboperations.com/wp-content/uploads/2009/05/gpp-running.png" alt="gpp-running" title="gpp-running" width="645" height="288" class="aligncenter size-full wp-image-1361" /></p>
<p>For ~20k links, it took almost 20 minutes for SiteSucker to grab them all. Take the finished log output and snip away the unneeded text to the left and right of the url. Go ahead and take the extra time to wrap them up in a nice anchor tag (this will help in the next step).</p>
<p>Copy this file and rename it to reflect the new site where you want to test your redirects. In your favorite editor search/replace the old domain with the test (or new) domain. Wrap it in with basic html &#038; body tags and change the extension to <code>.html</code>. Now, we have a very basic html page containing all the links from the old site. </p>
<p>In SiteSucker, go back into the settings and check the Limits. We want to enforce a maximum level of 1 now. This is because we already have all the relevant links in our file - no point in asking SiteSucker to recrawl the entire site for every original link (this would take <strong>days</strong>).<br />
<img src="http://www.agileweboperations.com/wp-content/uploads/2009/05/new-settings.png" alt="new-settings" title="new-settings" width="640" height="340" class="aligncenter size-full wp-image-1362" /></p>
<p>Finally, drag the html file you created (containing the test or new domain name and all links) into the Web URL bar and let go. SiteSucker dutifully follows every link and reports its findings. Hopefully, you won&#8217;t have too many ERRORs, but if you do, it&#8217;s quite easy now to rectify them as you have a log showing exactly which redirects failed!</p>
<p>Don&#8217;t let huge numbers of links frighten you into thinking you can&#8217;t make your site better. There are plenty of web crawlers available on many platforms - I have also used and recommend <a href="http://home.snafu.de/tilman/xenulink.html">Xenu</a> on Wine. Thinking a bit outside of the box can make it easy to turn that mountain into a mole hill again.</p>
<p>How do you maintain your sites&#8217; link &#8220;healthiness&#8221; ? Let us know in the comments.</p>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/acceptance-testing-with-cucumber/' rel='bookmark' title='Permanent Link: Acceptance Testing with Cucumber'>Acceptance Testing with Cucumber</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/using-sitesucker-for-testing-redirects/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Acceptance Testing with Cucumber</title>
		<link>http://www.agileweboperations.com/acceptance-testing-with-cucumber/</link>
		<comments>http://www.agileweboperations.com/acceptance-testing-with-cucumber/#comments</comments>
		<pubDate>Fri, 22 May 2009 08:35:06 +0000</pubDate>
		<dc:creator>Matthias Marschall</dc:creator>
		
		<category><![CDATA[Web Development & Operations]]></category>

		<category><![CDATA[agile]]></category>

		<category><![CDATA[cucumber]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1329</guid>
		<description><![CDATA[


Related posts:<ul><li><a href='http://www.agileweboperations.com/webrat-automated-acceptance-testing-with-rspec-or-cucumber/' rel='bookmark' title='Permanent Link: webrat: Automated Acceptance Testing with RSpec or Cucumber'>webrat: Automated Acceptance Testing with RSpec or Cucumber</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p><a href=""http://pivotallabs.com/talks/38-making-a-case-for-cucumber"><img src="http://cukes.info/images/cuke_tv_jeff_dean.png" alt="Pivotal Labs - Jeff Dean - Making a Case for Cucumber" /></a><br />
After watching a Pivotal Labs Tech Talk <a href="http://pivotallabs.com/talks/38-making-a-case-for-cucumber">Making a Case for Cucumber</a>, I decided to give it a try. Especially the seamless integration with rails and <a href="http://wiki.github.com/brynary/webrat">webrat</a> made me curious. Webrat is a headless browser simulator, which can execute UI tests for you. You even can use the same syntax to drive a real browser using Selenium if you need Javascript support for some of your tests.<br />
<span id="more-1329"></span></p>
<h3>Features</h3>
<p>For testing your application, you specify features consisting of scenarios. Each scenario is defined by a set of steps and validations. Here&#8217;s a short example:</p>

<div class="wp_syntax"><div class="code"><pre class="cucumber" style="font-family:monospace;">Feature Contact Form
  In order to tell us something
  users
  want to contact us online without having to leave their browser
&nbsp;
  Scenario: Submitting with valid infos
    Given I am on the contact page
    When I fill in &quot;Your Name&quot; with &quot;Matthias Marschall&quot;
    And I fill in &quot;Your Message&quot; with &quot;What's up?&quot;
    And I press &quot;Send&quot;
    Then I should see &quot;Thanks for your feedback!&quot;</pre></div></div>

<p>Usually, one would need to implement fixtures to bind steps to the application code. But cucumber comes with a very useful set of pre-defined steps for webrat, in fact, all of the above steps are already there. You should be able to successfully execute the above example out of the box (given your app already has the contact page up and running).</p>
<h3>Full Cycle E-Mail Testing with rails and cucumber</h3>
<p>Filling out the contact form should send an email to a feedback account with the information provided. There exists a very handy plugin for dealing with email verification in a rails test environment: <a href="http://github.com/bmabey/email-spec/tree/master">rspec-email</a></p>
<p>After installing it, you can add steps like these to the scenario shown above:</p>

<div class="wp_syntax"><div class="code"><pre class="cucumber" style="font-family:monospace;">    And &quot;contact@example.com&quot; should receive 1 email
&nbsp;
    When &quot;contact@example.com&quot; opens the email with subject &quot;Feedback&quot;
    Then I should see &quot;What's up&quot; in the email
&nbsp;
    When I click the first link in the email
    Then ...</pre></div></div>

<p>Again, all of the above steps are provided by the plugin (after calling script/generate&#8230;.).</p>
<p>Without writing a single line of fixture code, I was already able to do a full integration test including form validations and email sending. Not too bad for 2 hrs worth of research. My next steps will be to try out the selenium integration and play around with setting up data in the database for driving my tests. Stay tuned by subscribing to our <a href="http://feedproxy.google.com/agileweboperations">RSS feed</a>.</p>
&nbsp; 

<p>Related posts:<ul><li><a href='http://www.agileweboperations.com/webrat-automated-acceptance-testing-with-rspec-or-cucumber/' rel='bookmark' title='Permanent Link: webrat: Automated Acceptance Testing with RSpec or Cucumber'>webrat: Automated Acceptance Testing with RSpec or Cucumber</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/acceptance-testing-with-cucumber/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting a Quick Overview of your Site&#8217;s Response Times</title>
		<link>http://www.agileweboperations.com/getting-a-quick-overview-of-your-sites-response-times/</link>
		<comments>http://www.agileweboperations.com/getting-a-quick-overview-of-your-sites-response-times/#comments</comments>
		<pubDate>Sun, 17 May 2009 07:14:25 +0000</pubDate>
		<dc:creator>Dan Ackerson</dc:creator>
		
		<category><![CDATA[Web Development & Operations]]></category>

		<category><![CDATA[pingdom]]></category>

		<guid isPermaLink="false">http://www.agileweboperations.com/?p=1305</guid>
		<description><![CDATA[
I promised you a couple weeks back to share some more code for building your own XFD (extreme feedback device). Embedding Munin graphs is child&#8217;s play, so I thought I&#8217;d give you a head-start with the Pingdom API. And we all know how critical site response times are to the success of your online business.

Why [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/tidewatermuse/173598941/"><img alt="" src="http://farm1.static.flickr.com/45/173598941_e201092483_m.jpg" class="alignright" width="240" height="180" /></a><br />
I promised you a couple weeks back to share some more code for building your own <a href="http://www.agileweboperations.com/extreme-feedback-device-business-on-the-big-screen/">XFD (extreme feedback device)</a>. Embedding Munin graphs is child&#8217;s play, so I thought I&#8217;d give you a head-start with the Pingdom API. And we all know how critical <a href="http://books.google.de/books?id=o1IqPH0a2fYC&#038;pg=PA135&#038;vq=response+time&#038;dq=website+response+times+business&#038;hl=en&#038;source=gbs_search_s&#038;cad=0">site response times</a> are to the success of your online business.<br />
<span id="more-1305"></span></p>
<h3>Why not just login to Pingdom?</h3>
<p>Good question! My answer - because it&#8217;s slow &#038; tedious. It takes me minutes to get the information I&#8217;m looking for - namely, the average response time of a few critical pages from yesterday and today. To not have to click through the various cities <em>every day</em> deselecting all the [European|American] sites in order to get a more accurate measurement - this alone is worth its weight in gold!</p>
<p>Don&#8217;t get me wrong. The graphs are wonderful for spotting trends, but I don&#8217;t need to look at these every day. I want to be able to tell within a second or two if my site is performant.</p>
<h3>There&#8217;s a reason they made an API</h3>
<p>The good folks at Pingdom are number crunchers at heart - they probably also avoid logging into the site when possible because they developed <a href="http://www.pingdom.com/services/api-documentation/">a nice API</a> with which you can access all the info you need.</p>
<p>After requesting an API key, you&#8217;re just a few curl commands away from this :<br />
<img src="http://www.agileweboperations.com/wp-content/uploads/2009/05/pingdom.png" alt="pingdom" title="pingdom" width="386" height="133" class="aligncenter size-full wp-image-1307" /></p>
<p>And here&#8217;s the corresponding code:</p>
<pre lang=php>
&lt;?php
    define('SERVER_URL', 'https://ws.pingdom.com/soap/PingdomAPI.wsdl');
    define('USERNAME', '&lt;username&gt;');
    define('PASSWORD', '&lt;password&gt;');
    define('PINGDOM_API_KEY', '&lt;api_key&gt;');
    define('PINGDOM_API_STATUS_OK', 0);
    define('RESOLUTION', 'DAILY');
    define('GOOD_TIMING', 500);
    define('POOR_TIMING', 800);

    $client = new SoapClient(SERVER_URL, array( 'trace' =&gt; 1,'exceptions' =&gt; 0 ));

    $sessionId = loginPingdom($client);
    $responses = fetchPages($client, $sessionId);
    writeResponse($responses);
    logout($client, $sessionId);

function loginPingdom($client) {
    // Login
    $login_data->username = USERNAME;
    $login_data->password = PASSWORD;
    $sessionId = null;

    // Pingdom API function, see details on http://www.pingdom.com/services/api-documentation/
    $login_response = $client-&gt;Auth_login(PINGDOM_API_KEY, $login_data);

    // Check if everything is OK
    if (PINGDOM_API_STATUS_OK != $login_response-&gt;status) {
        echo'Unable to login to Pingdom';
    } else {
        // Without this value you wont be able to call any other Pingdom API function
        $sessionId = $login_response-&gt;sessionId;
    }

    return $sessionId;
}

function fetchPages($client, $sessionId) {
    $locs = array("Amsterdam, Holland","London, UK","Paris, France","Stockholm, Sweden");

    // Today - up through CURRENT_TIME
    $get_times_today-&gt;from = mktime("00", "00", "00", date("m"), date("d"), date("Y"));
    $get_times_today-&gt;to = CURRENT_TIME;
    $get_times_today-&gt;resolution = RESOLUTION;
    $get_times_today-&gt;locations = $locs;

    //Yesterday
    $get_times_yesterday-&gt;from = mktime("00", "00", "00", date("m") , date("d") - 1, date("Y"));
    $get_times_yesterday-&gt;to = mktime("23", "59", "59", date("m") , date("d") - 1, date("Y"));
    $get_times_yesterday-&gt;resolution = RESOLUTION;
    $get_times_yesterday-&gt;locations = $locs;

    // page names taken from how you entered them in Pingdom
    $pages_to_query = array('Homepage', 'Krankheiten', 'Asthma article');

    $responses = array();

    foreach ($pages_to_query as $checkName) {
        $response = null;

        $get_times_today-&gt;checkName = $checkName;
        $get_times_yesterday-&gt;checkName = $checkName;

        $times_today = $client-&gt;Report_getResponseTimes(PINGDOM_API_KEY, $sessionId, $get_times_today);
        $times_yesterday = $client-&gt;Report_getResponseTimes(PINGDOM_API_KEY, $sessionId, $get_times_yesterday);

        if (PINGDOM_API_STATUS_OK != $times_today-&gt;status ||
            PINGDOM_API_STATUS_OK != $times_yesterday-&gt;status) {
            echo('Error occurred while trying to get list of responsetimes');
        } else {
            $list_times_today = $times_today-&gt;responseTimesArray;
            $list_times_yesterday = $times_yesterday-&gt;responseTimesArray;

            $response-&gt;page = $checkName;
            $response-&gt;today = round($list_times_today[0]-&gt;responseTime);
            $response-&gt;yesterday = round($list_times_yesterday[0]-&gt;responseTime);

            $response-&gt;y_threshold = $response-&gt;yesterday &lt; GOOD_TIMING ? 'green' : ($response-&gt;yesterday &lt; POOR_TIMING ? 'orange' : 'red');
            $response-&gt;t_threshold = $response-&gt;today &lt; GOOD_TIMING ? 'green' : ($response-&gt;today &lt; POOR_TIMING ? 'orange' : 'red');

            $responses[] = $response;
        }
    }

    return $responses;
}

function writeResponse($responses) {
    $yesterday = date('d.m.Y', mktime(0, 0, 0, date("m") , date("d") - 1, date("Y")));
	$current = date('d.m.Y', CURRENT_TIME);

    echo "&lt;br/&gt;&lt;br/&gt;";
    echo "&lt;table class='responses' title='Response time (ms)' border='1'&gt;";
    echo "    &lt;tr&gt;";
    echo "        &lt;th&gt;&nbsp;Response Times&nbsp;&lt;/th&gt;";
    echo "        &lt;th&gt;&nbsp;$yesterday&nbsp;&lt;/th&gt;";
    echo "        &lt;th&gt;&nbsp;$current&nbsp;&lt;/th&gt;";
    echo "    &lt;/tr&gt;";

    foreach ($responses as $response) {
        $response_page = $response-&gt;page;
        $response_yest_thresh = $response-&gt;y_threshold;
        $response_toda_thresh = $response-&gt;t_threshold;
        $response_yesterday = $response-&gt;yesterday;
        $response_today = $response-&gt;today;

        echo "    &lt;tr&gt;";
        echo "        &lt;td&gt;$response_page&lt;/td&gt;";
        echo "        &lt;td&gt;&lt;span style='color:$response_yest_thresh;'&gt;$response_yesterday ms&lt;/span&gt;&lt;/td&gt;";
        echo "        &lt;td&gt;&lt;span style='color:$response_toda_thresh;'&gt;$response_today ms&lt;/span&gt;&lt;/td&gt;";
        echo "    &lt;/tr&gt;";
    }

    echo "&lt;/table&gt;";
}

function logout($client, $sessionId) {
    $logout_response = $client-&gt;Auth_logout(PINGDOM_API_KEY, $sessionId);
    if (PINGDOM_API_STATUS_OK != $logout_response-&gt;status) {
        echo('Error occurred while closing connection');
    }
}
?>
</pre>
<p>Of course, there are a few customizations you should make - namely the $locs, $pages_to_query, GOOD_TIMING &#038; POOR_TIMIING (both measured in msec) values. But, I hope I&#8217;ve gotten you off to a good start. </p>
<p>Questions, comments &#038; criticisms happily taken!</p>
&nbsp; 

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.agileweboperations.com/getting-a-quick-overview-of-your-sites-response-times/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.971 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2009-07-04 01:54:43 -->
<!-- Compression = gzip -->