[rspec-users] Test for a gem/plugin?

Pat Maddox pergesu at gmail.com
Thu Dec 11 13:55:41 EST 2008


James Byrne <lists at ruby-forum.com> writes:

> Matt Wynne wrote:
>> On 9 Dec 2008, at 19:06, James Byrne wrote:
>> 
>>> should
>>>
>>> When /authentication by authlogic/ do
>>>  #TODO: Find out how to test for a loaded gem within an application
>>> end
>> 
>> If you're working at the level of Cucumber features, I would stay well
>> away from implementation details like the particular technology you're
>> using for authentication.
>>
>
> The features for this simply say something along the lines of:
>
> Scenario: Application has known users
>   Given that the application has users
>   When the user signs on
>   Then the user is authenticated

WTBV?

(Where's the business value (I totally made that up, but I'm gonna stick
with it :))

On its own, being authenticated doesn't have any business value.
Authentication only *enhances* business value.  Consider a feature that
lets me manage finances.  That has some business value.  Then we ensure
that only authenticated users may manage their finances, which means we
can charge people for the service - enhancing the business value that
already exists.


>> Remember this is called Behaviour Driven Development[1] for a reason.
>> You're focussing on specifying the desired *behaviour* of the system.
>> How you chose to satisfy the user's need for that behaviour is an
>> entirely separate matter.
>
> Nonetheless, in the step definitions I must test the behaviour in a 
> fashion which first drives and then confirms the implementation
> details. 

I don't understand this.  Your features/specs drive the implementation,
but they confirm the *behavior*.


> If the chosen implementation depends upon a third party plugin or gem 
> then surely one should test for its provision?  What is the alternative? 
> Write tests to test that gems behaviour?

I would specify my app's behavior, not the gem's.  And I certainly
wouldn't test that the gem is there.  If it's not, then my code is going
to blow up anyway!

Instead, write features that specify *what* you want from your
application.

Given a user named 'padillac'
When I log in as 'padillac'
Then I should see 'Hello, padillac!'
And I should see 'Edit your account'

How you handle this - whether it's restful_authentication, authlogic, or
roll-your-own - doesn't matter.


>> A large benefit of having Acceptance Tests, IMO, is that you could
>> radically change your implementation under the hood, such as switching
>> to a different authentication mechanism, and the features would still
>> be valid. You might have to code up some of your steps a little
>> differently, but as long as the users want the same thing from the
>> system, the features should not have to change in the slightest.
>> 
>
> If the implementation changed then the step definitions must change to 
> suit, must they not?

It depends on the level at which you've written your step definitions.
If you've written them to hit the outer-most interface, for example
using webrat in a rails app, then no, you wouldn't need to change the
definitions.  If you wrote them at a lower level, creating a user and
adding his id to the session, then there's a chance you would have to
change them.

The key is writing the features themselves at a level of abstraction
that *completely* hides the implementation.  That way you can change
your code and step definitions freely.

What you're left with is a balancing act, deciding which implementation
details can force changes to your step definitions.  If you write the
definitions at a low level, accessing the model directly, you'll likely
need to change them when the definitions change.

On the other hand, if you write them at a higher level, there's the real
possibility that minor changes to your app code will necessitate changes
to your step definitions.  Consider the following step definition:

When /^I log in as '(.*)'$/ do |username|
  visits login_url
  fills_in 'Username', :with => username
  fills_in 'Password', :with => 'password'
end

If you change the template to read 'Login' instead of 'Username' for the
username field, the step definition is going to have to change.

So you have to evaluate each piece of your app, figure out what's likely
to change, determine the upfront and maintenance costs of writing step
definitions at varying levels of abstraction, and make a decision.  Then
be thankful that you're not building a bridge, because even if you get
it wrong, the cost of fixing your mistake is relatively cheap :)


> Not all features are of concern to all users/roles. Why should some 
> users be denied the use of features and BDD as a tool for their own 
> concerns simply because they are writing the code? It seems to me an 
> artificial, and logically insupportable, distinction to make.

I don't understand what you mean by this.  Which users are "denied the
use of features and BDD?"  Could you please elaborate for me?


> When /user "(.*)" is authenticated/ do |u|
>   # We use Authlogic for authentication so just test that gem is loaded
>   assert defined?("Authlogic")
> end

WTBV?! :)

Pat


More information about the rspec-users mailing list