Posts for category: crazy
A Given/When/Then Test Framework
Jim Weirich put up a potential Ruby test framework that steals the Given/When/Then syntax from Cucumber. I spent some time noodling along similar lines some months back but never got very far with it. Interestingly, Jim’s proposal and my idea seem to be a little bit different, so I thought I’d write up what I was trying to do, and maybe actually try and make it real.
I was thinking about a particular problem that’s easiest to see in a Rails controller test. Using Shoulda, and trying to use a nested context, one assertion per test style, I was trying to test admin and regular user behavior in a particular controller. I started with something like this:
context "GET edit" do
setup do
@proj1 = Project.make(:name => "Project Runway")
get :edit, :id => @proj1.to_param
end
should "have something" { assert something here}
end
Fine and dandy, but when I want to split this into admin and regular users, what I really want to do is this, bear with the slight pseduo-code:
context "GET edit" do
setup do
@proj1 = Project.make(:name => "Project Runway")
get :edit, :id => @proj1.to_param
end
context "with a normal user" do
setup { @user = login! }
should "have something" { assert something here}
end
context "with an admin user" do
setup { @user = admin! }
should "have something adminy" { assert something here}
end
end
Unfortunately this doesn’t work, since the get is called before the subordinate setup clauses, the user doesn’t take effect until after the controller call has been made. The workaround is to move the get call into the subordinate setup clauses, which is hardly the end of the world or anything like that but which did bug me a little.
Thinking about this, it occurred to me that the user set up is basically Given, while the get call is basically a When, and what I want to do is insert a new given, while keeping the same when.
I never did quite nail the syntax, but I was hoping for something like this
Scenario "GET edit" do
Given { @proj1 = Project.make(:name => "Project Runway") }
When { get :edit, :id => @proj1.to_param }
Scenario "For a normal user" do
Given { @user = login! }
Then { assert something here}
end
Scenario "For an admin user" do
Given { @user = admin! }
Then { assert something here}
end
end
The semantics of this is that any Then clause would trigger a test, first all the Given clauses would be run for all nested scenarios, then all the When clauses, followed by the Then block, which would need to return true for the test to pass.
I never got around to implementing it, in part for lack of time, and in part doubting whether this occasional case would be worth the extra effort. As much as I like how the Given/When/Then structure reads here, I’m not sure that it would be clear to a reader of this test that the subordinate Given clauses would be executed before the When clause. Though I guess that would come after some time with the framework.
Thoughts? Am I crazy?


