tag:blogger.com,1999:blog-81932217645066278692024-03-13T17:45:15.222+00:00Ryan GreenhallRyan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-8193221764506627869.post-617432459999743282010-03-19T21:11:00.003+00:002010-03-19T21:24:11.555+00:00QCon Day 2 Keynote: Ralph Johnson, Working and Living with Aging SoftwareA summary of Ralph Johnson's 2010 QCon keynote can be found <a href="http://www.ryangreenhall.com/2010/03/qcon-day-2-keynote-working-and-living-with-aging-software/"><span style="text-decoration: underline;">here</span></a>:Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com0tag:blogger.com,1999:blog-8193221764506627869.post-81280646822128008282009-01-13T16:58:00.006+00:002009-01-14T09:16:30.341+00:00Tired of Ant? Try Gant<a href="http://ant.apache.org/">Ant</a> has been a solid workhorse for building Java applications since its release in 2000, having many favorable properties including: cross platform, mature, provides a large collection of useful tasks and lets not forget the comprehensive documentation. However, Ant is showing its age and has been for some time. The use of XML to represent an<a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html"> external DSL</a> is now generally regarded as a mistake, not to mention noisy due to all of those angled brackets.<br /><p> Many in the Java community, especially those with experience with Rake from their Ruby adventures, have for some time been looking for alternative ways to build their applications. One noteworthy alternative is <a href="http://gant.codehaus.org/">Gant</a> (Groovy with Ant).<br /></p>Gant allows Ant tasks to be defined using Groovy. This approach provides an <a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html">internal DSL</a> for describing build tasks, which happens to be much more readable than its XML counterpart. Furthermore, users of Gant require very little Groovy knowledge to become productive. One only has to look at an example Gant script to see how Ant task definitions map to Gant definitions and away you go.<br /><br />One of the arguments I often hear against moving away from Ant is that almost every Java developer is familiar with Ant. Why would we want to move to something that fewer people know? With Gant this argument is not an issue as all of the Ant tasks that people have come to know and love are available. It is only the representation of those tasks that has changed.<br /><br />If your project is currently using Ant, you are happy with the functionality provided by Ant tasks, but can no longer stand to define your build script with XML. Gant may be just what you have been looking for.<br /><br />Here is an example Gant build file that performs a number of standard build operations, such as: compile, run tests, report test results and distribute as a jar.<br /><br /><h3>Example Gant Build</h3><br /><pre><code style=";font-family:Monaco;font-size:9pt;">sourceDirectory = <span style="color: rgb(0, 102, 0);">'src'</span><br />testDirectory = <span style="color: rgb(0, 102, 0);">'spec'</span><br />buildDirectory = <span style="color: rgb(0, 102, 0);">'build'</span><br /><br />sourceClassesDirectory = buildDirectory + <span style="color: rgb(0, 0, 0);">'/src'</span><br />specClassesDirectory = buildDirectory + '/spec'<br />testReportsDirectory = buildDirectory + '/junit-reports'<br />distributionDirectory = buildDirectory + '/dist'<br /><br />includeTargets << gant.targets.Clean<br />cleanPattern << '**/*~'<br />cleanDirectory << buildDirectory<br /><br />libDir = 'lib'<br /><br />def buildtimeDependenciesJars = ant.path(id: 'jars') {<br /> fileset(dir: libDir) {<br /> include(name: '*.jar')<br /> }<br />}<br /><br />target(compile: 'Compile source to build directory.') {<br /> mkdir(dir: sourceClassesDirectory)<br /> javac(srcdir: sourceDirectory, destdir: sourceClassesDirectory, debug: 'on')<br />}<br /><br />target(compileTests: 'Compile the examples') {<br /><br /> depends(compile)<br /><br /> mkdir(dir: specClassesDirectory)<br /> javac(srcdir: testDirectory, destdir: specClassesDirectory, debug: 'on') {<br /> classpath {<br /> path(refid: 'jars')<br /> pathelement ( location : sourceClassesDirectory )<br /> }<br /> }<br />}<br /><br />target ( test : 'Runs the examples') {<br /><br /> depends (compileTests)<br /><br /> mkdir(dir: testReportsDirectory)<br /> junit ( printsummary : 'yes' , failureproperty : 'testsFailed' , fork : 'true' ) {<br /> formatter ( type : 'plain' )<br /> classpath {<br /> pathelement ( location : specClassesDirectory )<br /> pathelement ( location : sourceClassesDirectory )<br /> path(refid: 'jars')<br /> }<br /><br /> batchtest ( todir : testReportsDirectory ) {<br /> fileset ( dir : testDirectory , includes : '**/*Behaviour.java' )<br /> }<br /> }<br />}<br /><br />target ( distribute : 'Distributes the library as a jar.') {<br /> depends (clean, test)<br /> mkdir(dir: distributionDirectory)<br /><br /> echo("Creating example-app.jar ...")<br /> jar ( destfile : distributionDirectory + '/example-app.jar' , basedir : sourceClassesDirectory )<br />}<br /><br />setDefaultTarget(distribute)<br /></code></pre>Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com1tag:blogger.com,1999:blog-8193221764506627869.post-50419625446295034722008-11-07T18:37:00.004+00:002008-11-07T19:20:52.815+00:00RSpec's Scenario Runner is dead - Long Live Cucumber!<p>Recently when browsing RSpec's homepage I noticed the bold (in the markup sense) announcement that RSpec's scenario runner has been deprecated in favour of Aslak Hellesøy's <a href="http://github.com/aslakhellesoy/cucumber/wikis">Cucumber</a>. I have always been a fan of RSpec's scenario runner and love the plain text story support. I therefore felt compelled to see what Cucumber has to offer and I am pleased to report that it's wonderful.</p><h3>First Taste of Cucumber</h3><p>Having previously used RSpec's scenario runner to provide automated acceptance scenarios for a Ruby implementation of the Game of Life, I was keen to see how easy it was to migrate to Cucumber.</p>Cucumber can be installed with the following command:<br /><pre face="Monaco" size="11pt" style=""><br /> gem install cucumber<br /></pre><h3>Feature Injection</h3>Cucumber is built around features rather than stories and recommends the Feature Injection template for describing features.<br /><br /><pre style=""><span style="font-size:100%;"><br /> In order to <b>[achieve value]</b><br /> As a <b>[role]</b><br /> I need <b>[feature]</b>.</span><br /></pre><p>I therefore revisited the create a cell story (originally found in the examples provided in the RSpec code base) and rephrased the requirement using the Feature Injection template.<br /></p> <h4>Story Format</h4><pre style="font-family: Monaco,monospace; font-size: 9pt;"><br />Story: Cell Creation<br /><br />As a game producer<br />I want to create a cell<br />So that I can set the initial game state<br /><br />Scenario:<br /> ...<br /></pre> <h4>Feature Injection Format</h4> <pre style=";font-family:Monaco;font-size:9pt;"><br />Feature: Cell Creation<br /><br />In order to set the initial game state<br />As a game player<br />I need to be able to create live cells.<br /><br />Scenario: Empty Grid<br /><br />Given a 3 x 3 game<br />Then the grid should look like<br />"...<br />...<br />..."<br /><br />Scenario: Create a single cell<br /><br />Given a 3 x 3 game<br />When I create a cell at 1, 1<br />Then the grid should look like<br />"...<br />.X.<br />..."<br /></pre> <h3>Convention over Configuration</h3>Cucumber applies a healthy dose of convention over configuration to provide a scenario runner that runs out of the box. The convention is to keep textual descriptions of features, using a .feature extension, in a features directory. Scenario steps are mapped to application code using Ruby. Step classes live in a steps directory as a child of the features directory.<br /><p> For example:<br /></p> <pre style="font-family: Monaco; font-size: 9pt;"> /features<br /> /steps<br /> game_of_life_steps.rb<br /> create-a-cell.feature<br /></pre><p> When following the prescribed directory structure, scenarios can be executed with the following command:<br /></p><pre style="font-family: Monaco; font-size: 9pt;"> rake features<br /></pre> <h3>Pending Steps</h3><p>Initially my game_of_life_steps.rb file did not define any steps. When executing the scenarios for the create cell feature Cucumber kindly told me which steps I needed to provide and even provided suggested implementations. This feature made me smile and was clearly developed in response to the question; how can I reduce the effort required to implement steps?<br /></p> <pre style=";font-family:Monaco;font-size:9pt;"> <span style="color:darkgoldenrod;">10 steps pending</span><br /><br /> You can use these snippets to implement pending steps:<br /><br /> Given /^a 3 x 3 game$/ do<br /> end<br /><br /> Then /^the grid should look like$/ do<br /> end<br /><br /> When /^I create a cell at 1, 1$/ do<br /> end<br /><br /> When /^I create a cell at 0, 0$/ do<br /> end<br /><br /> When /^I create a cell at 0, 1$/ do<br /> end<br /><br /> When /^I create a cell at 2, 2$/ do<br /> end<br /><br /></pre><h3>Implementing Steps</h3><p>Textual scenarios are mapped to code using a simple DSL that allows step patterns to be associated with the following step keywords: Given, When, Then. Each keyword accepts a Ruby block that will be executed when a step pattern is matched against an actual scenario step.</p><p>Steps can be parameterised using regular expressions, for example:<br /></p><div style="color:black;"><pre style=";font-family:Monaco;font-size:9pt;">require <span style="color:forestgreen;">"spec"</span><br /><br />require <span style="color:forestgreen;">"domain/game"</span><br />require <span style="color:forestgreen;">"view/string_game_renderer"</span><br /><br />Given <span style="color:blue;">/a (\d) x (\d) game/</span> do |x, y|<br /> <span style="color:purple;">@game</span> = Game.create(x.to_i, y.to_i)<br />end<br /><br />When <span style="color:blue;">/I create a cell at (\d), (\d)/</span> do |x, y|<br /> <span style="color:purple;">@game</span>.create_cell_at(x.to_i, y.to_i)<br />end<br /><br />Then <span style="color:blue;">/the grid should look like/</span> do |grid|<br /> StringGameRenderer.new(<span style="color:purple;">@game</span>).render.should eql(grid)<br />end<br /></pre></div><p>Alternatively, steps can be represented as strings using the dollar symbol to prefix a parameter.<br /></p><p>For example:</p><pre style="font-family: Monaco; font-size: 9pt;"> require <span style="color:forestgreen;">"spec"</span><br /><br />require <span style="color:forestgreen;">"domain/game"</span><br />require <span style="color:forestgreen;">"view/string_game_renderer"</span><br /><br />Given <span style="color:forestgreen;">"a $x x $y game"</span> do |x, y|<br /> <span style="color:purple;">@game</span> = Game.create(x.to_i, y.to_i)<br />end<br /><br />When <span style="color:forestgreen;">"I create a cell at $x, $y"</span> do |x, y|<br /> <span style="color:purple;">@game</span>.create_cell_at(x.to_i, y.to_i)<br />end<br /><br />Then <span style="color:forestgreen;">"the grid should look like$"</span> do |grid|<br /> StringGameRenderer.new(<span style="color:purple;">@game</span>).render.should eql(grid)<br />end<br /></pre><h3>Migrating away from Rspec's Story Runner</h3><p>Using RSpec's story runner I used the following approach to execute my scenarios:</p><ol><li>GameOfLifeSteps class extending Spec::Story::StepGroup</li><li>GameOfLifeStoryRunner class delegating to Spec::Story::Runner::PlainTextStoryRunner configured with the GameOfLifeSteps</li> <li>Story classes for each story that delegate to the GameOfLifeStoryRunner passing the filename of the story to execute</li><li>A Rake task to execute all of my stories</li></ol><p>At the time this did not seem too unreasonable although there was a significant learning curve figuring out how everything was configured. Cucumber solves the configuration problem using convention. Developers need to provide step definitions and Cucumber will handle the rest.</p><p>Migrating to Cucumber was largely an exercise in deleting code that was no longer required. The conversion from RSpec step definitions to Cucumber was painless as they are very similar.</p><h4>Example RSpec Step Definition<br /></h4><pre face="Monaco" size="9pt" style="">require<span style="color:forestgreen;">'spec/story'</span><br />require <span style="color:forestgreen;">"spec"</span><br /><br />require <span style="color:forestgreen;">"domain/game"</span><br />require <span style="color:forestgreen;">"view/string_game_renderer"</span><br /><br /><span style="color:blue;">class</span> GameOfLifeSteps < Spec::Story::StepGroup<br /><br /> steps do |define|<br /><br /> define.given(<span style="color:forestgreen;">"a $x x $y game"</span>) do |x, y|<br /> <span style="color:purple;">@game</span> = Game.create(x.to_i, y.to_i)<br /> end<br /><br /> define.when(<span style="color:forestgreen;">"I create a cell at $x, $y"</span>) do |x, y|<br /> <span style="color:purple;">@game</span>.create_cell_at(x.to_i, y.to_i)<br /> end<br /><br /> define.then(<span style="color:forestgreen;">"the grid should look like $grid"</span>) do |grid|<br /> StringGameRenderer.new(<span style="color:purple;">@game</span>).render.should eql(grid)<br /> end<br /> end<br />end<br /></pre><p>Readers will immediately appreciate how easy it is to convert from RSpec step definition format to the format required by Cucumber. Admittedly, my toy application is tiny in comparison to a typical production application, but I get the feeling that migrating a larger code base would not be too troublesome. The more adventurous may even wish to automate the migration process. More advice on migrating from RSpec scenarios can be found <a href="http://github.com/aslakhellesoy/cucumber/wikis/migration-from-rspec-stories">here</a></p><h3>Steady Evolution</h3><p>It is very encouraging to see the tooling around BDD evolve so that the task of mapping textual scenarios to code is now extremely simple. Certainly much easier than the previous generations of BDD frameworks. The Java community are well served by JBehave and the Ruby community now have Cucumber. Now that the technical challenges in mapping scenarios to code have largely been solved, teams can focus their efforts on collaborating with stakeholders and fellow team members to define the desired behaviour of the system being developed. After all, isn't that what BDD is all about?</p>Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com1tag:blogger.com,1999:blog-8193221764506627869.post-32742196870695923252008-10-21T09:13:00.004+01:002008-10-21T13:51:08.222+01:00Exposed Scenario Implementation<p>In my previous post I refactored a <a href="http://ryangreenhall.blogspot.com/2008/10/noisy-scenario-methods.html">noisy scenario method</a> so that it communicated the required scenario steps more clearly. Although this was a huge improvement in terms of readability the SignInAcceptanceScenarios class still has a significant weakness; maintainability due to the exposure of a number of implementation details.</p><p>Here is the current state of the sign-in scenario:</p><pre><br /><span style="color:blue;">public class</span> SignInAcceptanceScenarios {<br /><br /> <span style="color:blue;">private</span> WebDriver <span style="color:darkviolet;">driver</span>;<br /><br /> <span style="color:darkgoldenrod;">@Before</span><br /> <span style="color:blue;">public void</span> setup() {<br /> <span style="color:darkviolet;">driver</span> = new HtmlUnitDriver();<br /> }<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> shouldPresentKnownUserWithTheWelcomePage() {<br /><br /> Credentials credentials = new Credentials(<span style="color:green;">"ryangreenhall"</span>, <span style="color:green;">"password"</span>);<br /><br /> givenAnExistingUserWith(credentials);<br /> whenUserLogsInWith(credentials);<br /> thenTheUserIsPresentedWithTheWelcomePage();<br /> }<br /><br /> <span style="color:blue;">private void</span> givenAnExistingUserWith(Credentials credentials) {<br /> User user = new UserBuilder().<br /> withCredentials(credentials).<br /> build();<br /><br /> UserRespository respository = new UserRespository();<br /> respository.create(user);<br /> }<br /><br /> <span style="color:blue;">private void</span> whenUserLogsInWith(Credentials credentials) {<br /> browseToHomePage();<br /> enterUsernameAndPassword(credentials);<br /> clickSignInButton();<br /> }<br /><br /> <span style="color:blue;">private</span> WebDriver browseToHomePage() {<br /> <span style="color:darkviolet;">driver</span>.get(<span style="color:green;">"http://www.example.com/sign-in"</span>);<br /> return <span style="color:darkviolet;">driver</span>;<br /> }<br /><br /> <span style="color:blue;">private void</span> enterUsernameAndPassword(Credentials credentials) {<br /> <span style="color:darkviolet;">driver</span>.findElement(By.id(<span style="color:green;">"username"</span>)).sendKeys(credentials.getUserName());<br /> <span style="color:darkviolet;">driver</span>.findElement(By.id(<span style="color:green;">"password"</span>)).sendKeys(credentials.getPassword());<br /> }<br /><br /> <span style="color:blue;">private void</span> pressSignInButton() {<br /> <span style="color:darkviolet;">driver</span>.findElement(By.id(<span style="color:green;">"login"</span>)).submit();<br /> }<br /><br /> <span style="color:blue;">private void</span> thenTheUserIsPresentedWithTheWelcomePage() {<br /> Assert.assertEquals(<span style="color:green;">"Welcome"</span>, driver.getTitle());<br /> }<br />}<br /></pre><h3>Violating the Single Responsibility Principle</h3><p>Following the <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">Single Responsibility Principle</a> we know that a class should have only one reason to change. The SignInAcceptanceScenario is responsible for ensuring that the identified sign-in scenarios execute correctly. Let's consider how many reasons it has to change:</p><ol><li>The sign in resource changes: e.g. /log-in;</li><li>We want to replace Web Driver with another web testing framework;</li><li>The parameter names for username and password change;</li><li>The title of the welcome page changes;</li><li>The behaviour of the application changes;</li></ol><p>We have identified that our scenario class has five reasons to change! The only valid reason for this class to change is when the behaviour of the sign in process changes. For example, rather than presenting the user with the welcome page they are taken to their profile page, a common feature for most social networking sites these days.</p><p>Clearly with so many reasons to change, acceptance scenarios written in this style have the potential to require many changes throughout the lifetime of the application.</p><h3>Abstraction and Encapsulation to the Rescue</h3><p>Wouldn't it be great if we could encapsulate our scenarios from implementation details such as the location of the sign-in resource and the parameter names used to communicate the users credentials? This would allow the implementation of the application to change without modifying our scenarios.<br /></p><p>Currently when implementing the sign in scenario we are thinking in terms of the abstractions provided by the Web, for example, browse to the home page and submit parameters to a sign-in resource. Wouldn't it be great if we could raise the level of abstraction and just sign in to the application using credentials, asking the resulting page if it is the welcome page?<br /></p><p>Let's briefly consider one possible approach.</p><h3>Fluent Navigation</h3><p>Rather than exposing the implementation details of how we are interacting with application we need a suitable abstraction. One such abstraction involves representing each page in the application as a Page Object. The <a href="http://code.google.com/p/webdriver/wiki/PageObjects">Page Object Model</a>, introduced to me by my colleague <a href="http://dan.bodar.com/">Dan Bodart</a> and also recommended by the <a href="http://code.google.com/p/webdriver">WebDriver</a> team, nicely encapsulates the internal representation of a page and provides methods for appropriate interactions. Another nice feature of the Page Object Model is that we can make use of a <a href="http://www.martinfowler.com/bliki/FluentInterface.html">fluent interface</a> to allow seamless navigation through any number of pages.</p><p>The goal here is to demonstrate the value of introducing a suitable abstraction for interacting with the application. I will therefore leave detailed descriptions of the implementation in the interest of brevity.</p><h3>SignInPage</h3><p>Given that the scenario in the example involves signing in to the application we will need a SignInPage that allows credentials to be entered and submitted.</p><p>For example:<br /></p><pre><br /><span style="color:blue;">import</span> com.example.domain.Credentials;<br /><br /><span style="color:blue;">public class</span> SignInPage implements Page {<br /><br /> <span style="color:blue;">public</span> SignInPage() {<br /> }<br /><br /> <span style="color:blue;">public</span> SignInPage with(Credentials credentials) {<br /> <span style="color:purple;">// enter the username and password</span><br /> return this;<br /> }<br /><br /> <span style="color:blue;">public</span> Page submit() {<br /> <span style="color:purple;">// submit the username and password to the sign-in resource<br /> // and return a Page representation</span><br /> <span style="color:purple;">// of the response.</span><br /> }<br /><br /> <span style="color:blue;">public</span> String getTitle() {<br /> ...<br /> }<br />}<br /><br /></pre><h3>Application Facade</h3><p>Now that we have a SignInPage how can our SignInAcceptanceScenarios class get hold of one? The SignInPage will be dispensed by a class called MyApp, which acts a facade for the application providing methods to access various pages in the application. This approach nicely decouples the scenario from the URLs used to address pages in the application.<br /></p><p>For example:<br /></p><pre><br /><span style="color:blue;">import </span>com.example.web.pages.HomePage;<br /><span style="color:blue;">import </span>com.example.web.pages.Page;<br /><span style="color:blue;">import </span>com.example.web.pages.SignInPage;<br /><br /><span style="color:blue;">public</span> <span style="color:blue;">class</span> MyApp {<br /><br /> <span style="color:blue;">public</span> static SignInPage signIn() {<br /> <span style="color:purple;">// GET the sign in page and return a sign in page object</span><br /> }<br />}<br /></pre><h3>Matching Pages</h3><p>We now have the ability to navigate to the sign-in page, enter the users credentials and submit, receiving a resultant page. The only remaining functionality required by the sign-in scenario is to ensure that the page returned as a result of submitting user credentials is the welcome page. How can we encapsulate the sign-in scenario from knowing the internals of the welcome page? This sounds like a job for a <a href="http://code.google.com/p/hamcrest/">Hamcrest</a> matcher. We will create a WelcomePageMatcher that knows if a given page is the welcome page by inspecting the title of the page.</p><p>For example:<br /></p><pre><br /><span style="color:blue;">import </span>org.hamcrest.BaseMatcher;<br /><span style="color:blue;">import </span>org.hamcrest.Description;<br /><span style="color:blue;">import </span>com.example.web.pages.Page;<br /><br /><span style="color:blue;">public class </span>WelcomePageMatcher extends BaseMatcher {<br /><br /> <span style="color:blue;">public</span> boolean matches(Object actualPage) {<br /> return <span style="color:green;">"Welcome"</span>.equals(((Page)actualPage).getTitle());<br /> }<br /><br /> <span style="color:blue;">public</span> void describeTo(Description description) {<br /> }<br /><br /> <span style="color:blue;">public</span> static WelcomePageMatcher isWelcomePage() {<br /> return <span style="color:blue;">new</span> WelcomePageMatcher();<br /> }<br />}<br /><br /></pre><h3>Bringing Everything Together<br /></h3><p>The application facade, SignInPage and WelcomePageMatcher can be combined to provide a very concise specification of the behaviour required when users sign-in to the example application.<br /></p><pre><br /><span style="color:blue;">import</span> com.example.domain.builders.UserBuilder;<br /><span style="color:blue;">import</span> com.example.domain.Credentials;<br /><span style="color:blue;">import</span> com.example.domain.User;<br /><span style="color:blue;">import</span> com.example.persistence.UserRespository;<br /><span style="color:blue;">import</span> static com.example.web.MyApp.signIn;<br /><span style="color:blue;">import</span> com.example.web.pages.Page;<br /><span style="color:blue;">import</span> static com.example.web.pages.matchers.WelcomePageMatcher.isWelcomePage;<br /><span style="color:blue;">import</span> org.junit.Test;<br /><br /><span style="color:blue;">public class</span> SignInAcceptanceScenarios {<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> shouldPresentKnownUserWithTheWelcomePage() {<br /> Page pageAfterLogIn = null;<br /> Credentials credentials =<br /> new Credentials(<span style="color:green;">"ryangreenhall"</span>, <span style="color:green;">"password"</span>);<br /><br /> givenAnExistingUserWith(credentials);<br /> whenUserLogsInWith(credentials, pageAfterLogIn);<br /> thenUserIsPresentedWithTheWelcomePage(pageAfterLogIn);<br /> }<br /><br /> <span style="color:purple;">// Alternatively we could have:</span><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> shouldPresentKnownUserWithTheWelcomePage() {<br /> Credentials credentials =<br /> new Credentials(<span style="color:green;">"ryangreenhall"</span>, <span style="color:green;">"password"</span>);<br /><br /> <span style="color:purple;">// Given</span><br /> givenAnExistingUserWith(credentials);<br /><br /> <span style="color:purple;">// When</span><br /> Page pageAfterLogin = signIn().with(credentials).submit();<br /><br /> <span style="color:purple;">// Then</span><br /> ensureThat(pageAfterLogin, isWelcomePage());<br /> }<br /><br /> <span style="color:purple;">// Alternatively we can combine the when and then steps in a single line:</span><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> shouldPresentKnownUserWithTheWelcomePage() {<br /> Credentials credentials =<br /> new Credentials(<span style="color:green;">"ryangreenhall"</span>, <span style="color:green;">"password"</span>);<br /><br /> givenAnExistingUserWith(credentials);<br /><br /> ensureThat(signIn().with(credentials).submit(),<br /> respondsWithWelcomePage());<br /> }<br /><br /><br /> <span style="color:blue;">private void</span> givenAnExistingUserWith(Credentials credentials) {<br /> User user = new UserBuilder().<br /> withCredentials(credentials).<br /> build();<br /><br /> UserRespository respository = new UserRespository();<br /> respository.create(user);<br /> }<br /><br /> <span style="color:blue;">private void</span> whenUserLogsInWith(Credentials credentials, Page pageAfterLogIn) {<br /> pageAfterLogIn = signIn().with(credentials).submit();<br /> }<br /><br /> <span style="color:blue;">private void</span> thenUserIsPresentedWithTheWelcomePage(Page pageAfterLogin) {<br /> ensureThat(page, isWelcomePage());<br /> }<br />}<br /></pre><h3>Summary</h3><p>We have seen that the introduction of a simple internal <a href="http://martinfowler.com/bliki/DomainSpecificLanguage.html">DSL</a> to interact with the application has greatly improved the readability of this scenario. Furthermore the SignInAcceptanceScenarios class is now completely decoupled from the implementation of the application making it less susceptible to change.</p><p>We can now change the following concerns without modifying the SignInAcceptanceScenario:</p><ol><li>Location of the sign in resource (encapsulated in the SignInPage class);</li><li>Web testing framework (encapsulated in both the Application Facade and Page classes);</li><li>The parameter names for username and password (encapsulated in the SignInPage);</li><li>The title of the welcome page changes (encapsulated in the WelcomePageMatcher);</li></ol><p>The SignInAcceptanceScenarios class now has only one responsibility; defining the behaviour of the application and thus should only require modification when the behaviour of the application changes.</p>Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com0tag:blogger.com,1999:blog-8193221764506627869.post-68563245344251740852008-10-19T15:34:00.004+01:002008-10-19T16:39:36.135+01:00Noisy Scenario Methods<p>This is the second entry in a series of posts that provide practical advice on how to avoid or refactor away from common functional testing smells.</p><p>Noisy scenario methods can generally be identified by the presence of long methods, which fail to highlight the important interactions with the application clearly. The code driving the application will typically be at a low level of abstraction adding to the noise. For web applications this will involve requesting resources, posting parameters and ensuring the expected response is returned. For example:<br /></p><pre><br /> <span style="color: blue">public class</span> SignInAcceptanceScenarios {<br /><br /> <span style="color: darkgoldenrod">@Test</span><br /> <span style="color: blue">public void</span> shouldPresentKnownUserWithTheWelcomePage() {<br /><br /> User user = new UserBuilder().<br /> withUsername(<span style="color: green">"ryangreenhall"</span>).<br /> withPassword(<span style="color: green">"password"</span>).<br /> build();<br /><br /> UserRespository respository = new UserRespository();<br /> respository.create(user);<br /><br /> WebDriver driver = new HtmlUnitDriver();<br /> driver.get(<span style="color: green">"http://www.example.com"</span>);<br /><br /> driver.findElement(By.id(<span style="color: green">"username"</span>)).sendKeys(<span style="color: green">"ryangreenhall"</span>);<br /> driver.findElement(By.id(<span style="color: green">"password"</span>)).sendKeys(<span style="color: green">"password"</span>);<br /> driver.findElement(By.id(<span style="color: green">"login"</span>)).submit();<br /><br /> Assert.assertEquals(<span style="color: green">"Welcome"</span>, driver.getTitle());<br /> }<br /> }<br /></pre><p>When reading scenarios I like to see clear descriptions of the steps that are taken when interacting with the application. The main problem with noisy scenario methods is that the reader has to filter through the noise to figure out the following: what is the starting state of the system? What interactions occur? An additional problem is that the reader is required to think at a low level of abstraction. Rather than thinking about signing in to the application we are forced to think in terms of posting parameters representing the username and password to a sign-in resource.</p><h3>Discovering the Scenario Steps</h3><p>Reading the example scenario we can see that ensuring a known user is presented with the welcome page requires the following steps:</p><ol><li>Create a user</li><li>Navigate to the applications home page</li><li>Fill in the sign in form with known credentials</li><li>Submit the signin form</li><li>Ensure that the user is taken to the welcome page</li></ol><p>Some would argue that the example scenario could be improved with the introduction of comments prior to each step. However, I favour scenarios that are composed of small methods, whose names clearly describe: the starting state of the application, the interactions with the application and the expected outcomes. This allows the scenario to be expressed in terms of the domain without distracting the reader with the implementation details.</p><p>The Given-When-Then scenario format popularised by <a href="http://dannorth.net/introducing-bdd/">Behaviour Driven Development</a> is a good starting point for structuring scenarios.</p><h3>Making Your Code Read Like a Scenario</h3><p>The following example shows how the original scenario has been improved using a series of Extract Method refactorings in order to communicate the important steps in the scenario, namely: create a new user, sign in with known credentials and ensure that the user is presented with the welcome page.</p><pre><br /> <span style="color: blue">public class</span> SignInAcceptanceScenarios {<br /><br /> <span style="color: blue">private</span> WebDriver <span style="color: darkviolet">driver</span>;<br /><br /> <span style="color: darkgoldenrod">@Before</span><br /> <span style="color: blue">public void</span> setup() {<br /> <span style="color: darkviolet">driver</span> = new HtmlUnitDriver();<br /> }<br /><br /> <span style="color: darkgoldenrod">@Test</span><br /> <span style="color: blue">public void</span> shouldPresentKnownUserWithTheWelcomePage() {<br /><br /> Credentials credentials = new Credentials(<span style="color: green">"ryangreenhall"</span>, <span style="color: green">"password"</span>);<br /><br /> givenAnExistingUserWith(credentials);<br /> whenUserLogsInWith(credentials);<br /> thenTheUserIsPresentedWithTheWelcomePage();<br /> }<br /><br /> <span style="color: blue">private void</span> givenAnExistingUserWith(Credentials credentials) {<br /> User user = new UserBuilder().<br /> withCredentials(credentials).<br /> build();<br /><br /> UserRespository respository = new UserRespository();<br /> respository.create(user);<br /> }<br /><br /> <span style="color: blue">private void</span> whenUserLogsInWith(Credentials credentials) {<br /> browseToHomePage();<br /> enterUsernameAndPassword(credentials);<br /> clickSignInButton();<br /> }<br /><br /> <span style="color: blue">private</span> WebDriver browseToHomePage() {<br /> <span style="color: darkviolet">driver</span>.get(<span style="color: green">"http://www.example.com/sign-in"</span>);<br /> return <span style="color: darkviolet">driver</span>;<br /> }<br /><br /> <span style="color: blue">private void</span> enterUsernameAndPassword(Credentials credentials) {<br /> <span style="color: darkviolet">driver</span>.findElement(By.id(<span style="color: green">"username"</span>)).sendKeys(credentials.getUserName());<br /> <span style="color: darkviolet">driver</span>.findElement(By.id(<span style="color: green">"password"</span>)).sendKeys(credentials.getPassword());<br /> }<br /><br /> <span style="color: blue">private void</span> pressSignInButton() {<br /> <span style="color: darkviolet">driver</span>.findElement(By.id(<span style="color: green">"login"</span>)).submit();<br /> }<br /><br /> <span style="color: blue">private void</span> thenTheUserIsPresentedWithTheWelcomePage() {<br /> Assert.assertEquals(<span style="color: green">"Welcome"</span>, driver.getTitle());<br /> }<br /> }<br /></pre><p>Structuring scenario methods in this style allows the reader to quickly understand the behaviour expected of the application in the context of a given scenario. Furthermore given that they read like written scenarios in terms of the problem domain they can be used to assist in conversations with QAs and Business Analysts, in addition to serving as useful documentation for future maintainers.</p>Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com0tag:blogger.com,1999:blog-8193221764506627869.post-37646418138908715162008-10-16T17:26:00.005+01:002008-10-16T17:37:21.134+01:00Mind Mapping Behaviour Driven Development<p>I recently presented an overview of Behaviour Driven Development at my current client. To help gather my thoughts I created the following mind map and have made it available here as others may find it useful.<br /></p><br /><img src="http://www.ryangreenhall.com/images/bdd/mind-mapping-bdd.jpg" alt="mind-mapping-bdd" height="90%" width="90%" /><p>This mind map distills information from the following sources:</p><ul><li>Dan North's <a href="http://dannorth.net/introducing-bdd/">Introducing BDD</a></li><li><a href="http://en.wikipedia.org/wiki/Behavior_driven_development">Wikipedia's BDD entry</a></li><li><a href="http://behaviour-driven.org/">behaviour-driven.org</a></li><br /></ul>Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com0tag:blogger.com,1999:blog-8193221764506627869.post-24588468325990490352008-10-14T20:14:00.002+01:002008-10-14T20:34:59.578+01:00Non Descriptive Scenario Method Name<p>This is the first entry in a series of posts that provide practical advice on how to avoid or refactor away from common functional testing smells.</p><p>Non descriptive scenario method names can easily be identified by the presence of extremely short method names that provide little or no insight into the scenario being executed. For example:</p><pre><br /> <span style="color:blue;">public class </span>SignInAcceptanceScenarios {<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> signIn() {<br /> ...<br /> }<br /> }<br /> </pre><p>So, what sign in scenario is being executed here? Known user? Unknown user? The only way to find out is to read what the method is doing. Variations on this theme include partial attempts to describe the scenario. For example:<br /></p><pre><br /> <span style="color:blue;">public class </span>SignInAcceptanceScenarios {<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> signInHappyScenario() {<br /> ...<br /> }<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> signInSadScenario() {<br /> ...<br /> }<br /> }<br /> </pre><p>Using story and scenario identifiers in scenario method names should also be avoided. Who would like to hazard a guess as to what behaviour the following scenarios describe?<br /></p><pre><br /> <span style="color:blue;">public class </span>SignInAcceptanceScenarios {<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> story145Scenario1() {<br /> ...<br /> }<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> story145Scenario2() {<br /> ...<br /> }<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> story345Scenario1() {<br /> ...<br /> }<br /> }<br /> </pre><p> The use of scenario revealing method names in each of the examples would be far more helpful.<br /></p><h3>Scenario Revealing Method Names</h3><p>I tend to prefer descriptive method names that describe the scenario being executed. A downside of this style is that it can lead to some very long method names. However, I would rather read a longer method name than a shorter one that has some important part of the scenario missing. Alternatively, if method names get ridiculously long then they can often be rephrased in a more concise manner. Personally I don't worry too much about long method names. When writing scenarios I aim for an accurate and clear description of the scenario being executed.<br /></p><p>Non descriptive scenario methods can easily be renamed, once the scenario has been understood, so that the scenario is clearly described using a scenario revealing method name. For example:<br /></p><pre><br /> <span style="color:blue;">public class</span> SignInAcceptanceScenarios {<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> shouldPresentKnownUserWithTheWelcomePage() {<br /> ...<br /> }<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> shouldDeclineUnknownUserAndAskThemToTryAgain() {<br /> ...<br /> }<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> shouldLockAccountAfterThreeSubsequentFailedSignInAttempt() {<br /> ...<br /> }<br /> }<br /> </pre><p>A subtle alternative to prefixing scenario method names with 'should' is to simply provide a description of the expected behaviour. I shall leave it as an exercise for readers to decide which style they prefer. My only advice, as with most things when developing software, is to be consistent. For example:<br /></p><pre><br /> <span style="color:blue;">public class</span> SignInAcceptanceScenarios {<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> knownUserIsPresentedWithTheWelcomePage() {<br /> ...<br /> }<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> unknownUserIsDeclinedAndAskedToTryAgain() {<br /> ...<br /> }<br /><br /> <span style="color:darkgoldenrod;">@Test</span><br /> <span style="color:blue;">public void</span> userAccountIsLockedAfterThreeSubsequentFailedSignInAttempts() {<br /> ...<br /> }<br /> }<br /> </pre><p>Scenario revealing methods are a huge improvement over their less descriptive counterparts, allowing readers to quickly grasp the intended behaviour <br />of a given functional area. The improved SignInAcceptanceScenarios class really does serve as documentation describing the behaviour of the sign in functionality provided by the application.<br /></p>Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com2tag:blogger.com,1999:blog-8193221764506627869.post-78304319864138763452008-09-30T15:29:00.007+01:002008-10-02T08:51:46.359+01:00The Rise of Modern Legacy Code<p style="text-align: left;">Legacy code, as defined by <span style="font-family:helvetica, arial, sans;">Michael </span>Feathers in <a href="http://www.objectmentor.com/resources/books.html">Working Effectively with Legacy Code</a>, is code that is without tests and difficult to change. I would like to suggest that there is a new breed of legacy code emerging with the increasing adoption of Test Driven Development and more recently Behaviour Driven Development; Modern legacy code.</p><p style="text-align: left;">These days, if you are lucky, you may encounter code bases with large suites of both unit and functional tests (perhaps I should say examples, specs or scenarios these days!). However, in some cases, although these tests serve as a reliable regression suite guarding against defects being introduced when adding new features, they may fail to clearly describe the desired behaviour of the system clearly.</p><p style="text-align: left;">In my opinion modern legacy code is code that has good functional and unit test coverage, but where the tests (especially functional) fail to clearly communicate the desired behaviour of the application increasing the cost of maintenance. This is a shame as with a little care and focus on readability it is possible to write functional tests that really do serve as documentation describing the behaviour of the application.</p><p style="text-align: left;">Should the concept of modern legacy be used as an excuse to not write functional tests? Absolutely not. Modern legacy should be a term that is used both to encourage teams to search for better ways to express their tests with the goal of improving readability and to seek out approaches that make functional tests easier to write. Modern legacy is a huge improvement over traditional legacy but there is still plenty of room for improvement in how we ensure that our applications are behaving themselves.</p><p style="text-align: left;">In a future post I plan to identify common functional test smells that I have encountered and to provide practical advice on how to spruce them up so that they describe the behaviour of the application more clearly.</p><p style="text-align: left;">In the meantime have a look at the functional tests in your application. Do they clearly describe the behaviour of your application? A good acid test is to ask a developer from another team if they can understand what your application is supposed to do by reading the functional tests for a given functional area. If you observe a puzzled stare followed by a series of WTFs then you may have some modern legacy code.<br /></p>Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com0tag:blogger.com,1999:blog-8193221764506627869.post-32138874661848930332008-09-28T20:00:00.008+01:002008-09-29T06:16:24.401+01:00What is The Role of QA?<h2 style="text-align: justify;">Zero Defects!</h2><p style="text-align: justify;">What would you think of a QA who told you that they had not found a single defect in the last month?</p><ul style="text-align: justify;"><li>Lazy?</li><li>Unimaginative?</li><li>Been on holiday?</li><li>An accomplished QA?</li></ul>The answer to this question depends solely on how one views the role of QA in the development process. Let's consider two hugely contrasting views of the role of QA in the context of two very different styles of development.<br /><p></p><h2>Team Foo</h2><p>Team Foo work in a waterfall manner where each function of development: requirements, analysis, design, coding and QA are performed by different groups, in series. Communication among the different groups is achieved through documentation, with many members of the various teams having never met in person.<br /></p><p>After a period of development, QA receive a "completed" system and have to answer the following question, often presented by management: Is the developed system fit for purpose, or in other words can we ship? This is a huge responsibility.</p><p>The sad reality for QAs working within this process is that they play no part in defect prevention to assist in ensuring the desired quality. They are only able to either detect the absence of quality through the identification of defects, or acknowledge that the system is of sufficient quality to be released. QAs therefore embark on a quest to find as many defects a possible. After all who wants to to be responsible for "signing off" a defect ridden product into production?<br /></p><p>QAs adopt a destructive mindset and actively attempt to break the system using usage scenarios that may or may not be realistic; after all a shared understanding of the acceptance criteria for each feature has not been established. Bug reports are entered into the bug tracking system, assigned to development and the code and fix cycle begins. Bug fixes introduce new defects resulting in rising tensions and frustration between developers and QA and ultimately a late delivery.</p><p>Anyone has has worked in similar team setup will tell you that defects are common place. To make matters worse development and QA often engage in debates about whether raised bugs are in fact defects or a misinterpretation of the requirements.</p><p>Defects are expected in this environment and in some cases might be used as a measure of quality - "we have found and fixed 89 defects - we have a quality product now". Any claim of finding zero defects would almost certainly be frowned upon and may be used as a metric to suggest poor performance.<br /></p><h2 class="section-heading">Team Bar<br /></h2><p>Team Bar form a cross functional team comprised of business people, business analysts, developers and QAs sitting on the same floor, within earshot of one another. The team work collaboratively toward a common goal set by the business who actively work with technical people to ensure that they understand the risks and opportunities provided by the project.</p><p>QA are heavily involved in the analysis of requirements and work closely with business analysts to define the acceptance criteria that features must fulfill to be deemed complete. Prior to starting work on a story, developers engage in a conversation with QAs to ensure that the acceptance criteria is understood. During this conversation it is not uncommon for developers to say something like: "We seemed to have missed the timeout scenario. What shall we do in this case?" The QA may reply "Oh yes, I didn't think of that, let's retry for a maximum of three times".</p><p>Upon completion of a feature, developers provide a demonstration to both QAs and business analysts to verify that their work fulfills the acceptance criteria defined for the feature. Any defects or missing features identified at this stage can be resolved efficiently by the original developer (or developers if pairing).<br /></p><p>The goal for QA is to ensure that quality is built into the product from the beginning. The acceptance criteria used to judge the product's quality is clearly communicated to the whole team to ensure that the correct product is built. QA will still independently verify that the acceptance criteria for each story has been fulfilled.</p><p>A zero defect rate would be celebrated and considered to be a result of close collaboration between QAs, business analysts and developers both prior to and throughout development of features. QAs will have worked hard to identify realistic scenarios prior to features being developed and will have clearly communicated the acceptance criteria by which features will be deemed complete.<br /></p><h2 class="section-heading">Changing Opinions on the focus of QA<br /></h2><p>It is very interesting to note that QA communities, predating the Agile and Lean movements, acknowledge that the focus of QA has changed considerably as the discipline has matured and developed over the past fifty years.<br /><br />In the paper, <a href="http://portal.acm.org/citation.cfm?id=62959.62965">The Growth of Software Testing (1988) </a>, the shifting focus of QA is categorized as follows:<br /></p><table><br /><tbody><tr><br /><th style="text-align: left;">Period</th><br /><th style="text-align: left;">Focus</th><br /></tr><br /><tr><br /><td>1956</td><br /><td width="70%"><br /><b>Debugging</b> - Programs are written and then tested by the programmer until they are satisfied that any bugs have been removed.<br /></td><br /></tr><br /><tr><br /><td>1957 - 1978</td><br /><td><br /><b>Demonstration</b> - Testing demonstrates that the system does what it is supposed to do.<br /></td><br /></tr><br /><tr><br /><td>1979 - 1982</td><br /><td><br /><b>Destruction</b> - The focus of testing changes from proving the system does what is supposed to do, to the identification of defects.<br /></td><br /></tr><br /><tr><br /><td>1983 - 1987</td><br /><td><br /><b>Evaluation</b> - Testing becomes an activity throughout the development life cycle.<br /></td><br /></tr><br /><tr><br /><td>1988</td><br /><td><br /><b>Prevention</b> - The focus is on defect prevention. Tests were written to demonstrate that software satisfies its specification, to detect faults and to prevent faults.<br /></td><br /></tr><br /></tbody></table><br /><p>Perhaps Test Driven Development is not so extreme after all?<br /></p><h2 class="section-heading">Zero Defects - Really?<br /></h2><p>I have known of several projects that fit the profile of the Bar team. Did they achieve zero defects? The honest answer is no. They did, however, reduce defects to a manageable level. Unpredictable, demoralising cycles of code and fix have been long forgotten on these teams. Where a defect is found it is followed up with a root cause analysis to determine how the defect was introduced so that it can be avoided in the future.</p><p>Note that while QAs in the Bar team place heavy emphasis on defect prevention they still ensure that the behaviour required of the system is present and correct according to the specified acceptance criteria.<br /></p><h2 class="section-heading">Summary</h2><p>In both teams the goal of QA is to ensure that the system is fit for purpose and provides the features agreed with the customer. We have seen two contrasting styles of development and the different roles that QA plays in each. Team Foo focus on the identification of defects and bug reporting whereas Team Bar focus on preventing defects.<br /></p><p>The <a href="http://www.poppendieck.com/ilsd.htm">Poppendieck's</a> have it right when they describe a process that regularly results in defects being found as a broken process. Defects should be a rarity rather than the norm. If identification of defects is commonplace in your organisation then you have a problem.</p><p>Software development has suffered for too long as a result of poor collaboration between QA and development. What can you do to encourage collaboration between these two groups? You could try starting with the following statement: As a company we value defect prevention over defect identification.<br /></p>Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com2tag:blogger.com,1999:blog-8193221764506627869.post-84328729243554844492008-09-06T11:09:00.004+01:002008-09-06T13:46:33.145+01:00Behaviour Driven Development: by ExampleTo coincide with the release of the wonderful <a href="http://jbehave.org/">JBehave 2</a>, I have made available an introductory BDD article, <a href="http://www.ryangreenhall.com/articles/bdd-by-example.html">Behaviour Driven Development: By Example</a>, using JBehave 2 as the example BDD framework.<br /><br /> The goal of the article is to introduce newcomers to BDD using a worked example, documenting a BDD style development process starting with a story scenario through to working code.<br /><br />Comments and suggestions for improvements are most welcome.<br /><br />If you are working in a Java development team who are envious of RSpec's Story Runner, and JRuby is a little too radical for your environment, then JBehave 2 is just what you have been waiting for.<br /><br />Congratulations to the JBehave 2 team!Ryan Greenhallhttp://www.blogger.com/profile/05219938031058010998noreply@blogger.com1