<?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>Vonk's Blog &#187; selenium</title>
	<atom:link href="http://blog.larsvonkconsultancy.nl/tag/selenium/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.larsvonkconsultancy.nl</link>
	<description>Blogs about Software Development, Agility and all the Rest</description>
	<lastBuildDate>Fri, 31 Jul 2009 13:51:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>FitNesse Scenario are the Bomb</title>
		<link>http://blog.larsvonkconsultancy.nl/2009/07/fitnesse-scenario-are-the-bomb/</link>
		<comments>http://blog.larsvonkconsultancy.nl/2009/07/fitnesse-scenario-are-the-bomb/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 13:22:31 +0000</pubDate>
		<dc:creator>Lars Vonk</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[fitnesse]]></category>
		<category><![CDATA[scenarios]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[slim]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://blog.larsvonkconsultancy.nl/?p=89</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://blog.larsvonkconsultancy.nl/2009/07/tdd-tips/">previous blog</a> on TDD I advocated that you should define your test on a high level. One of the reasons why you should use a high level language is that you can use your tests not only for your API but also for for instance your UI. In this blog I will show how you can use the same test pages in FitNesse to test both the API and UI of your system.</p>
<p><span id="more-89"></span></p>
<p>Using <a href="http://fitnesse.org/FitNesse.UserGuide.SliM" onclick="pageTracker._trackPageview('/outgoing/fitnesse.org/FitNesse.UserGuide.SliM?referer=');">Slim</a> Scenario fixtures this can be implemented fairly easy. Scenarios are Slim tables that can be called form other Slim tables. For a step by step tutorial on how to apply Scenarios I recommend watching Bob Martin&#8217;s <a href="http://vimeo.com/3323573" onclick="pageTracker._trackPageview('/outgoing/vimeo.com/3323573?referer=');">screencast</a>. </p>
<p>With a few additions to Bob Martin&#8217;s video you can use that test for both API and UI.</p>
<p>Lets say we have the following BDD style test:</p>
<pre class="brush: plain;">
given a current maximum capacity of 2 and 1 items already planned
then I can lower the maximum capacity to 1
then I can not lower the maximum capacity to 0
</pre>
<p>Using scenarios this would end up in the following FitNesse markup:</p>
<pre class="brush: plain;">
!|scenario|given a current maximum capacity of |maxCapacity| and |itemsPlanned| items already planned|
|set maximum capacity to|@maxCapacity|
|plan|@itemsPlanned|items|

!|scenario|then I can lower the maximum capacity to|newMaxCapacity|
|ensure|set maximum capacity to|@newMaxCapacity|

!|scenario|then I can not lower the maximum capacity to|newMaxCapacity|
|reject|set maximum capacity to|@newMaxCapacity|

!|script|MaxCapacityApiDriver|

!|script|
|given a current maximum capacity of |2| and |1| items already planned|
|then I can lower the maximum capacity to |1|
|then I can not lower the maximum capacity to |0|
</pre>
<p>And the fixture would look like this:</p>
<pre class="brush: java;">
public class MaxCapacityApiDriver {

	private Capacity capacity = new Capacity();

	public boolean setMaximumCapacityTo(int max) {
		try {
			capacity.setMax(max);
			return true;
		} catch(MoreItemsThanCapacityException e) {
			return false;
		}
	}

	public void planItems(int items) {
		for(int x=0; x&lt;items; x++) {
			capacity.plan();
		}
	}
}
</pre>
<p>Now if we look at the example we could also apply this to our maintenance user interface where the admin can actually change the max capacity.</p>
<p>Using selenium-rc this can be implemented fairly easy. I choose to keep the FitNesse pages the same, the only thing I change is the driver that is used. </p>
<p><strong>Step 1. Extract Scenario</strong></p>
<p>we do not want to duplicate the scenarios so we extract the scenarios to a seperate page. We can then include this page using the !include directive in FitNesse.</p>
<p>Our test FitNesse markup now looks like this:</p>
<pre class="brush: plain;">
!include ScenarioPage

!|script|MaxCapacityApiDriver|

!|script|
|given a current maximum capacity of |2| and |1| items already planned|
|then I can lower the maximum capacity to |1|
|then I can not lower the maximum capacity to |0|
</pre>
<p><strong>Step 2. Extract Test</strong></p>
<p>Wait a minute. We also want to reuse our BDD style test. Let&#8217;s do the same trick as we did using the ScenarioPage.</p>
<p>After extracting the Test our FitNesse markup looks like this:</p>
<pre class="brush: plain;">
!include ScenarioPage

!|script|MaxCapacityApiDriver|

!include TestPage
</pre>
<p><strong>Step 3. Implement Driver</strong></p>
<p>Now all we have to do is implement the UI driver.</p>
<pre class="brush: plain;">
!include ScenarioPage

!|script|MaxCapacityUiDriver|

!include TestPage
</pre>
<p>This is how the fixture code could look like using <a href="http://seleniumhq.org/projects/remote-control/" onclick="pageTracker._trackPageview('/outgoing/seleniumhq.org/projects/remote-control/?referer=');">selenium-rc</a>, I left out some plumbing for readability</p>
<pre class="brush: java;">
public class MaxCapacityUiDriver {

	private Selenium selenium;

	public boolean setMaximumCapacityTo(int max) {
		selenium.open(&quot;/capacity/change&quot;);
		selenium.type(&quot;maximum&quot;, String.valueOf(max));
		selenium.click(&quot;changeMaxButton&quot;);
		selenium.waitForPageToLoad(TIMEOUT);
		return selenium.isTextPresent(&quot;successfully changed capacity to: &quot;
				+ max);
	}

	public void planItems(int items) {
		selenium.open(&quot;/items&quot;);
		for (int x = 0; x &lt; items; x++) {
			selenium.click(&quot;planItem&quot;);
			selenium.waitForPageToLoad(TIMEOUT);
		}
	}
}
</pre>
<p>Using FitNesse scenarios and extracting pages to include them is very handy when you want to re-use some tests. Please keep in mind that it is not wise to test your application code through your UI, so apply this carefully. I tend to pick only a few scenarios to see if the UI and API communicate properly.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larsvonkconsultancy.nl/2009/07/fitnesse-scenario-are-the-bomb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
