Graphical workflow tests for Rails - alpha version released
For many web apps, it’s important to get the user’s workflow right. Consider a Rails app that uses some variant of acts as authenticated to handle user registration and login. Here’s one way of describing an example of normal registration:
John visits the home page.
John follows the “sign up” link.
(John is now on the signup page.)
John signs up as “john”, email “john@example.com”, password “sloop”.
(John is now on the welcome page.)
John waits for activation email…
John clicks on a URL ending in an activation code.
(John is now on the login page.)
John logs in as “john”, password “sloop”.
(John is now on the member page.)
Here’s another:
Which is better? If I were trying to design the workflow—get it so that it’s right for the users—I’d much rather use a picture (whether drawn in OmniGraffle, as this was, or on a napkin or whiteboard.) Why?
-
It’s easier to “zoom out” from a picture, to ignore the details. When I do that, I’m more likely to notice missing workflows or stupidities in the ones that I have.
-
As a designer, I’ll soon have to explain my thinking to others. It’s easier to explain a picture because it’s sitting right there in front of both of you, visible in two-dimensional space. It’s simple to refer to something you already mentioned: point at it. A wealth of context gets recalled by that simple gesture. If it’s not readily recalled, you can decorate the graphic with something that jogs the memory. Pictures make for a much more fluid way of communicating.
-
Our minds are in bodies; and bodies have minds of their own. We think kinesthetically and visually, not (just) by banging propositions together according to the rules of some kind of logic. The more ways you think about something, the fewer mistakes you’ll make.
But there’s one big disadvantage of pictures from the point of view of the test-driven (behavior-driven, example-driven) programmer: they’re not executable.
I’ve released an alpha version of an open-source library that converts such pictures into Ruby tests. Below the fold, I show how the workflow picture becomes a Rails integration test.
✂——✂——✂——✂——✂——✂——✂——✂——✂——✂——
To make the picture executable, you first need code to parse the OmniGraffle document. That’s pretty easy. Then you need to interpret three different kinds of elements of the picture:
-
Labels on lines need to be turned into appropriate GET or POST messages. For example, ‘john logs in as “john”, “sloop”‘ can turn into a call of this method:
def john_logs_in_as(name, password)
post_via_redirect(action_for_link(”login”),
:user => {
:login => name,
:password => password
})
assert_response :success
end(Notice that I’m not using POST directly. Instead, I’m building a set of methods that’s at the same level of abstraction as the picture. I want to separate the issue of turning a designer’s intention into Ruby from the issue of what HTTP implements that intention.)
-
Icons contain their own name (capitalized for emphasis). They need to be turned into calls to this method:
def assert_on_page(page)
assert_template page.downcase.gsub(/\s+/, “”)
end -
Finally, there’s one special case: the text “John waits for activation email…” looks to OmniGraffle much like an icon, but it needs to be treated like a label. That is, it should turn into a call to this method:
def john_waits_for_activation_email
assert_equal([@user_email_address],
@sent.collect { |m| m.to[0] })
assert_equal(”Welcome, Giant Microbe Fan”,
@sent.first.subject)
end(Notice that this method is by no means a complete check of the email. That should be done by some more localized, non-workflow, tests. The methods for these tests answer the question “did the right thing happen?”, not “is what happened right in all details?”)
Given the appropriate interpreter-of-graphics, the above picture gets turned into these method calls:
@target.send(’john_visits_home_page’) @target.send(’john_follows’, “sign up”) @target.send(’assert_on_page’, “signup”) @target.send(’john_signs_up_as’, “john”, “john@example.com”, “sloop”) @target.send(’assert_on_page’, “welcome”) @target.send(’john_waits_for_activation_email’) @target.send(’john_clicks_on_url_ending_in_activation_code’) @target.send(’assert_on_page’, “login”) @target.send(’john_logs_in_as’, “john”, “sloop”) @target.send(’assert_on_page’, “member”) |
This test happens to fail. That looks like this:
What next? And what about you?
I’m building a site to learn Rails, and I’ll continue writing graphical tests for it. I expect that I’ll add new types of graphical tests; I have in the past. The tricky part is going to be figuring out a balance: on the one hand, you want designers and product directors to be able to sketch freely and not be bound by the tool. (They should not be taking on much more additional work.) On the other hand, the programmers shouldn’t have to do much work beyond what they’d do if they were writing tests directly in Ruby. What I need is some sort of
“language” for describing how pictures are to be interpreted that’s powerful enough, simple enough, etc. - all those things that are so hard to get right at the same time. For reference, here’s how I “program the interpreter” now:
class UserRegistrationTest < ActionController::IntegrationTest include GraphicalTestsForRails … graphics = InWorkflowOrder.new(doc.first_sheet).graphics interpreter = GraphicInterpreter.new(graphics, ‘line labels’ => ArgsFromQuotedText.new, ’shaped graphic text’ => TextIsNameOfPage.new(‘assert_on_page’), ‘text…’ => ArgsFromQuotedText.new) interpreter.run_against(self) |
The more people I have trying this on their own sites (and helping with language design), the better it will turn out. Let me know if you’re interested.
July 22nd, 2007 at 1:55 pm
[…] if you’re making gems anyway (like I’m doing these days), s4t-utils might as well be another gem your gem depends on. So s4t-utils is now available from […]
October 15th, 2007 at 1:38 pm
[…] one of my graphical tests. The input is in a form pleasing to a non-technician. In this case, the test is failing. The output […]
November 20th, 2007 at 5:46 pm
[…] Space, but oriented toward showing rather than telling. For example, I’d be happy to show my graphical workflow tests in action—if people want to see […]
November 29th, 2007 at 6:41 pm
[…] been growing a little disillusioned with my graphical workflow tests: implementing the test support code seems like a lot of work for little benefit. (It has nothing to […]
February 6th, 2009 at 11:49 am
[…] a demo of what he accomplished after 10 minutes of playing with CubicTest. It reminded me of the graphical workflow test for rails Brian Marick was working […]
February 12th, 2012 at 11:57 am
[…] like Fit/FitNesse, Cucumber, and my old Omnigraffle tests allow you to write what I call “rhetoric-heavy” business-facing tests. All […]