Presenting at RailsConf 2008

January 26th, 2008

I’m going to be presenting at RailsConf 2008 on RSpec’s Story Runner. I’ll be talking about how I approach writing for the Story Runner and address several related issues including:

<ul>
<li>plain text stories vs pure Ruby (when is which appropriate?)</li>
    <li>extending the RailsStory with custom helpers</li>
    <li>testing forms using <a href="http://agilewebdevelopment.com/plugins/webrat">webrat</a> within the Story Runner</li>
    <li>finding a balance of domain and UI scenarios</li>
    <li>duplication between stories/scenarios and model/view/controller/helper examples</li>
</ul>


<p>That&#8217;s probably already more than I can cover fairly in a 45 minute presentation, but feel free to make other suggestions if you have them.</p>


<p>See you in Portland!</p>

RSpec: new –pattern option

January 20th, 2008

Updated on 27 May, 2008

<p>I&#8217;m not in the habit of blogging every change we make to RSpec, but this one <strong>may</strong> change the way your suite behaves if you have not been following convention.</p>


<p>As of RSpec&#8217;s trunk revision 3246 there is a new command line option that lets you control the filename pattern to match. This allows you to restrict files that are loaded when running the spec command in the same way that you can with rake. It also means that helper files that you may depend on are no longer loaded implicitly.</p>


<p>The default is:</p>

"spec/**/*_spec.rb".

To get rspec to behave as it did before this change, use this:

--pattern "spec/**/*.rb"

If you prefer naming your spec files “foo_example.rb”, you can do this:

--pattern "spec/**/*_example.rb"

You can also supply multiple patterns (comma separated):

--pattern "spec/**/_example.rb, spec/*/*_spec.rb"

This is a very handy way to avoid loading resource files (helpers, matchers, etc) except when you require them explicitly from other files.

<p>This is currently only in trunk, but will be part of the next release.</p>

Presenting at QCon London

January 9th, 2008

I’m pleased to report that I’m going to be presenting at QCon London in March. Aslak Hellesøy, Dr. Nic Williams, Kevin Clark and I have been invited to present about various aspects of The Rise of Ruby.

<p>We&#8217;ll also be running <a href="http://qcon.infoq.com/london/schedule/monday.jsp">tutorials on Monday</a>. Aslak and I will present <a href="http://qcon.infoq.com/london/presentation/Ruby+for+Java+%26+C%23+programmers">Ruby for Java and C# Programmers</a> and Dr. Nic will present on <a href="http://qcon.infoq.com/london/presentation/Rails">Rails</a>.</p>

Advanced Rails Recipes

January 4th, 2008

I’m pleased to announce that my contribution to Mike Clark’s new Advanced Rails Recipes book has been accepted and released. The book is available right now as a Beta PDF and includes dozens of delicious and nutritious recipes for enhancing your Rails applications and the process of developing them.

<p>This is my first formal publication in the software world [1], and I couldn&#8217;t be more pleased than to have it be a <a href="http://www.pragprog.com/titles">Pragmatic Bookshelf</a> [2] publication.</p>


<p>My recipe is entitled Describing Behaviour from the Outside-In With RSpec and it demonstrates the <span class="caps">BDD</span> approach to Rails apps starting with the view and working your way down to the controllers, models and database.</p>


<p>There is currently one other <span class="caps">BDD</span> recipe: Getting Started with <span class="caps">BDD</span>, which uses <a href="http://thoughtbot.com/projects/shoulda">shoulda</a>. There are also recipes for cooking up mocks, code coverage and html validity. And that&#8217;s just the testing related recipes.</p>


<p>There are also dozens of recipes dealing with UI, search, email, console, <span class="caps">REST</span>, db enhancements and even more general design improvements.</p>


<p>Like the first <a href="http://www.pragprog.com/titles/fr_rr">Rails Recipes</a> book, this one is a must-have for any serious Rails developer who wants to take it up a notch in creating great web applications with Rails.</p>

[1] My first publication of any kind was back around 1980 when I was a young professional magician. The book is called, simply, Coin Magic, and is a must have for any serious coin magician who wants to take it up a notch (see a trend here?) in presenting awesome feats of magic with ordinary coins. Back then I went by my first and middle name, David Arthur.

<p>[2] The <a href="http://www.pragprog.com/">Pragmatic Programmers</a> are also publishing my upcoming book with co-author <a href="http://blog.aslakhellesoy.com/">Aslak Helles&oslash;y</a>, tentatively entitled Behaviour Driven Development in Ruby with RSpec.</p>

RubyConf 2007 Talk

December 7th, 2007

The RSpec/BDD talk that Dave Astels and I presented at RubyConf 2007 has been posted for your viewing pleasure.

<p>There are also a bunch of other RubyConf talks <a href="http://rubyconf2007.confreaks.com/">posted on the same site</a>.</p>


<p>One correction: In our talk, I said that the role/feature/reason story format came from Mike Cohn&#8217;s book User Stories Applied. The real source was a project team at Connextra that Tim MacKinnon was a part of. Tim later joined Thoughtworks, where Dan North learned about it from Tim.</p>


<p>I did, in fact, learn about it from Mike Cohn, but it was at a talk he did at an Agile Conference a couple of summers back. I had also read his book, and somewhere in my head merged the talk and the book.</p>

Nested Example Groups

November 29th, 2007

Since rspec first appeared on the scene, users have been asking for nested example groups. Well it has finally arrived. RSpec 1.1.0 will ship with support for nesting, so you’ll be able to do things like this:


describe RSpec do
  before(:each) do
    @rspec = RSpec.new
  end

describe "at release 1.0.8" do before(:each) do @rspec.version = "1.0.8" end

it "should not support nested example groups" do
  @rspec.should_not support_nested_example_groups
end

end

describe “at release 1.1.0″ do before(:each) do @rspec.version = “1.1.0″ end

it "should support nested example groups" do
  @rspec.should support_nested_example_groups
end

end end

This will output:

RSpec at release 1.0.8
- should not support nested example groups

RSpec at release 1.1.0 - should support nested example groups

If you’re using trunk, you can do this now with revision 3009 or later.

<p>Happy nesting!</p>

RubyConf slides

November 5th, 2007

Here are the slides from the presentation that Dave Astels and I did at RubyConf 07.

Lessons in Spec'ing

October 26th, 2007

Lesson: system calls in specs do stuff on your system. Be careful.

<p>I was trying different things to understand why a spec was failing and, at one point, put a pending statement in a spec that generates a file and then deletes it. The statement that deletes the file is in an after(:each) block (which is guaranteed to run) and looks like this:</p>

system(%Q|rm "#{dir}/#{filename}"|)

Imagine my horror when I saw this in the output:

rm: /: is a directory

Plain Text Stories: Part III

October 25th, 2007

Here’s the latest update to Plain Text Stories. Effective r2789 in RSpec’s trunk.

<p>Step 1: Write a Story</p>

Story: simple addition

As an accountant I want to add numbers So that I can count beans

Scenario: add one plus one Given an addend of 1 And an addend of 1

When the addends are added

Then the sum should be 2
And the corks should be popped

Scenario: add two plus five Given an addend of 2 And an addend of 5

When the addends are added

Then the sum should be 7

Step 2: Create Steps

# This creates steps for :addition
steps_for(:addition) do
  Given("an addend of $addend") do |addend|
    @adder ||= Adder.new
    @adder << addend.to_i
  end
end

This appends to them

steps_for(:addition) do When("the addends are added") { @sum = @adder.sum } Then("the sum should be $sum") { |sum| @sum.should == sum.to_i } end

Step 3: Let her open the box … no, that’s not it …

<p>Step 3: Run the Story with the steps you want (adding any that are only for this story as you go).</p>

with_steps_for :addition do
  Then("the corks should be popped") {}
  run 'path/to/story/file'
end

Working with Rails?

with_steps_for :navigation do
  run 'path/to/story/file', :type => RailsStory
end

What about multiple groups of steps?


with_steps_for :login, :navigation, :form_submissions do
  run 'path/to/story/file'
end

Coming soon to a computer near you … (as soon as you can “seven up”)

Plain Text Stories on Rails

October 22nd, 2007

Since my last post on plain text stories, there have already been a few improvements, not the least of which is that it will now work with Rails. Again, this is trunk (rev 2769+) only and experimental.

<p>Here&#8217;s a working example from an app that I&#8217;m working on:</p>

stories/login

Story: registered user logs in
  As a registered user
  I want to have to log in
  So that only other registered users can see my data

Scenario: user logs in and sees welcome page Given a user registered with login: foo and password: test When user logs in with login: foo and password: test Then user should see the welcome page

Scenario: user logs in with wrong password Given a user registered with login: foo and password: test When user logs in with login: foo and password: wrong Then user should see the login form And page should include text: There was an error logging in.

Scenario: user logs in with wrong login name Given a user registered with login: foo and password: test When user logs in with login: wrong and password: test Then user should see the login form And page should include text: There was an error logging in.

[Update: modified to use runner.steps instead of runner.step_matchers]

stories/login.rb

require File.join(File.dirname(FILE), *%w[helper])

run_story :type => RailsStory do |runner| runner.steps << LoginSteps.new runner.steps << NavigationSteps.new runner.load File.expand_path(FILE).gsub(".rb","") end

Here’s what’s new in this example:

<ul>
<li>run_story is added to the main object so you don&#8217;t have to remember that silly path to the PlainTextStoryRunner which will undoutedbly change!</li>
    <li>run_story accepts arguments, including an options hash, which it will pass to the constructor of the PlainTextStoryRunner (in this case, :type =&gt; RailsStory)</li>
    <li>run_story yields the runner, which now supports a load method which you use to tell it where to find the plain text story file.</li>
    <li>run_story &#8230; runs the story</li>
</ul>


<p>Keep your eyes peeled for more updates in the coming days.</p>