Cucumber has been getting quite a bit of attention in the community and with the new RSpec Book on nearing publication, I predict that by this time next year, it’ll become a household word like boanthropy.
What is Cucumber?
The Cucumber project describes itself as a suite that, “lets software development teams describe how software should behave in plain text. The text is written in a business-readable domain-specific language and serves as documentation, automated tests and development-aid – all rolled into one format.“
One of the great things about Cucumber is that it can be used to test applications in any language. I haven’t been able to track down a lot of articles of how people are using it with other languages, so please comment if you’re aware of some.
In any event, I’ve been collecting and reading resources from a variety of Cucumber aficionados and thought I’d share some links with you. To round it out, I asked on twitter for some others so that I could hit twenty. :-)
- What’s in a Story?, Dan North
- Telling a good story – Rspec stories from the trenches, Joseph Wilk
- Beginning with Cucumber, Ryan Bates (Railscasts)
- Using RSpec, Cucumber and User stories to build our internal systems, Rahoul Baruah
- Cucumber: The Latest in Ruby Testing, Ruby Inside
- Using Cucumber for Acceptance Testing, Noel Rappin
- Behavior Driven Development with Cucumber, Brandon Keepers (presentation/slides)
- Testing capistrano recipes with cucumber, Jeff Dean
- Using Cucumber to Integrate Distributed Systems and Test Messaging, Ben Mabey
- Tutorial: How to install/setup Cucumber, Alan Mitchell
- Testing outbound emails with Cucumber, Dr. Nic Willians
- Proper Cucumber Sintatra Driving, Chris Strom
- On getting started using Cucumber for .NET
- DRY up your Cucumber Steps, Matt Wynne
- Cucumber, Celerity, & FireWatir, Aidy Lewis (presentation/video)
- Cucumber step definition tip: Stubbing time, Bryan Helmkamp
- Story Driven Development Recipes with Cucumber, Sebastien Auvray
- Testing Facebook with Cucumber, Brandon Keepers
- Testing with the help of machinist, forgery, cucumber, webrat and rspec, Etienne van Tonder
- Integration testing SSL with Cucumber
- Continuous Integration Blueprints: How to Build an Army of Killer Robots With Hudson and Cucumber
So.. there you have it. Please post comments with links to any useful articles not mentioned and I’ll try to keep the list updated.
FREE RECIPE: Cucumber Water
And now…for the reason you are all here! If you like cucumbers (eating them)... I would highly recommend heading to your local farmers market and purchasing some cucumbers. Aside from being healthy to eat… they can help make a tasty beverage.
Then do the following…
- Chop several slices of a cucumber
- Fill a pitcher with cold water and ice
- Toss in slices of cucumber
- Stir and leave in fridge for a while
- Take out of fridge, pour into cup…
- Drink… hack… and enjoy
Be sure to check out, How to Make Cucumber Water on wikihow for details.
Related Posts (by me)
I meant to work on this post… oh about 7 months ago.
Way back in January (7 months ago), Jamis Buck posted an article titled, Testing your views, which gave a few tips on using Test::Unit to, as the title suggests, test your views.
While, I’m not going to rewrite everything that Jamis wrote, I’d like to show you how to test these views with RSpec. (you might take a moment to quickly read his post…)
In this example, I’m going to show you how we’re able to write specs for the following RHTML, which you’ll notice matches the code that he wrote tests for.
<% if @user.administrator? %> Hi <%= @user.name %>! You appear to be an administrator. <%= link_to "Click here", admin_url, :id => "admin_link" %> to see the admin stuff! <% end %>
Jamis writes, “The only really significant thing you ought to be testing here is that the admin link only shows up for administrators. “
So, let’s do just that, but with RSpec.
I’m not sure how Jamis is handling his view tests, but we’re going to approach our view specs, much like we approach our controller specs, with the use of mocks and stubs, because we really don’t need to spec any of our models at this level in the application.
Tip: Write specifications for your models… in your model specs not in your controller or view specs.
The first thing that we’re going to do is setup a custom spec helper, because for something like an mocked user, will probably get reused in other areas of the user interface. Spec helpers are essentially modules that you can include in your RSpec descriptions (the block that starts with
describe) and reuse.
In this spec helper, I’m going to include two methods, to mock the User model and stub out any of the methods that are necessary for spec’n this view.
module MockUserHelper def mock_normal_user user = mock(User) user.stub!(:administrator?).and_return(false) # <--- NOT an admin user.stub!(:name).and_return('David Chelimsky') return user end def mock_admin_user user = mock(User) user.stub!(:administrator?).and_return(true) # <--- IS an admin user.stub!(:name).and_return('Aslak Hellesoy') return user end end
mock_normal_user method, we’re constructing a mock object and stubbing out the methods that we see are being called in the RHTML code. In
mock_admin_user, we’re basically doing the same thing, but just stubbing the
administrator? method to return
true for this mock user.
By stubbing these methods, we’ll be able to send a non-ActiveRecord object to the view and have it render without knowing the difference. For example, the
if @user.administrator? condition will return true or false, depending on how we stubbed it.
For more information on mocks and stubs, read here.
Now that we have our spec helper, let’s go ahead and dive into a few specifications for the view.
describe "index page" do include MockUserHelper it "should render an admin link for an admin user" do assigns[:user] = mock_admin_user render 'index' response.should have_tag('a#admin_link') end it "should not render an admin link for a normal, non-admin user" do assigns[:user] = mock_normal_user render 'index' response.should_not have_tag('a#admin_link') end end
Please note: This code example is only longer than the one shown by Jamis because he didn’t include how he setup all his user sessions/objects. ;-)
When these specs are run, we can see the following results.
Pretty output courtesy of RSpec + TextMate bundle
Great, we’ve been able to write specifications for our Rails views without a lot of pain. Stay tuned for more posts on this topic as I continue writing about how Designers and Developers can work together, in harmony. (see my last post on this topic)
For more information on adopting RSpec, please visit the RSpec project homepage.
Josh Knowles just mentioned an article written by David Chelminsky, titled, an introduction to RSpec – Part I. In this article, David introduces you to some of the new language that appeared in some of the recent versions of RSpec as well as give you a complete tutorial on building some specs.
Last night, I had the opportunity to sit down with Aslak Hellesøy and David Chelimsky for a few hours and talk about my experiences of using RSpec at PLANET ARGON and how it’s helped us redefine and evolve our process. In particular, how RSpec has helped us reshape our process of gathering user interaction specifications from our Interaction Design team and business rules from our clients.
If you’re in town and are using RSpec… or are thinking about using RSpec… and see these guys… thank them for all the hard work that they’re doing… and of course, if you run into anybody else on the team... do the same. :-)
I love to look at other peoples code. Initially, that’s what got me excited about Open Source software. Otherwise, I was looking at small snippets on various developer sites and really not getting the complete picture for how everything tied together.
Last night, I finally had a chance to checkout the sample caboose application, which was created as a way for people to get an idea for how some of developers in caboo.se are putting together their applications.
Some things that you might want to check out it’s using…
It’s definitely worth taking 15 or so minutes to check it out and get some fresh ideas.
There are a few things that I’m not quite sure that didn’t quite make sense, so… perhaps I’ll submit a patch. :-)
svn co svn://caboo.se/plugins/court3nay/empty_apps/tags/v_003
I still believe that Behavior-Driven Development is kinkier than Test-Driven Development...
I’m currently reading To Engineer is Human, by Henry Petroski and found the following applicable to software development and managing client and customer expectations.
“As much as it is human to make mistakes, it is also human to want to avoid them. Murphy’s Law, holding that anything that can go wrong will, is not a law of nature but a joke. All the light bulbs that last until we tire of the lamp, all the shoelaces that outlast their shoes, all the automobiles that give trouble-free service until they are traded in have the last laugh on Murphy. Just as he will not outlive his law, so nothing manufactured can be or is expected to last forever. Once we recognize this elementary fact, the possibility of a machine or a building being as near to perfect for its designed lifetime as its creators may strive to be for theirs is not only a realistic goal but also a reasonable expectation for consumers. It is only when we set ourselves such an unrealistic goal as buying a shoelace that will never break, inventing a perpetual motion machine, or building a vehicle that will never break down that we appear to be fools and not rational beings.”
I’m sure that most of us are guilty of having high expectations for products that we purchased. (why does my ipod screen scratch so easily when in my pocket?) We also set high expectations for the code that we develop, which is why we (hopefully) continue to refine our process. We’re bound to time and budget constraints, which often prevent us from testing every imaginable edge case. Given our constraints, problems are almost always going to arise. It’s no wonder that we see Test-Driven Development as an important part of a healthy development process. We want to catch our failures as early as possible.
Our clients often have high expectations and it’s almost always very reasonable. That’s not to say that some clients will not have highly irrational expectations. It’s our job to manage these expectations as best as possible.
Do we mislead our clients by convincing them that our TDD/BDD process is going to prevent any bugs from creeping from the woodwork after the development cycle is finished?
“I thought that we paid you to fully test the code?”
Really… is that even possible? Can we predict (and test) every possible interaction within an application? Highly unlikely.
What we can do is plan for and embrace failure. We can help our clients understand that almost every application needs to be maintained after it’s initial development cycle. Bugs are inevitable and there needs to be a clear process for handling them.
Perhaps I’m abusing the bug fixing process by calling it a failure… but I’ve also found that yes… many bugs are due to failure. Whether that be a failure to specify application behavior, a failure to understand the project goals, a failure in communication, ...or maybe a failure in our software architecture. We’re constantly failing.. and it’s okay!
IT’S OKAY TO FAIL! (some of the time…)
“No one wants to learn by mistakes, but we cannot learn enough from successes to go beyond the state of the art. Contrary to their popular characterization as intellectual conservatives, engineers are really among the avant-garde. They are constantly seeking to employ new concepts to reduce the weigh and thus the cost of their structures, and they are constantly striving to do more with less so the resulting structure represents an efficient use of materials. The engineer always believes he is trying something without error, but the truth of the matter is that each new structure can be a new trial. In the meantime the layman, whose spokesman is often a poet or writer, can be threatened by both the failures and the successes. Such is the nature not only of science and engineering, but of all human endeavors.”
As we’re creating these virtual structures… are we really taking the time to reflect on our failures? This is why some teams adopt practices like iteration retrospectives and post-mortems.
I’ll end this with a few questions, which I hope that you’ll share your experiences about…
- In what ways is your team embracing the failures of your development projects?
- How do you help manage your clients expectations… so that they too can plan for and embrace failure? Isn’t their new business venture on the web… likely to experience some failure?
We have so much to learn…
Older posts: 1 2