Forum: RSpec Persisting Logins and Sessions across scenarios

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
171ea139761951336b844e708d1547ab?d=identicon&s=25 James Byrne (byrnejb)
on 2009-01-12 17:45
I have an authentication filter on my application controller. I have the
following feature statements:


  Scenario: I should be logged in to do any of this
    Given we have a user named "myuser"
      And the user named "myuser" logs in
    When they visit the "entities" page
    Then they should see the "entities" page


  Scenario: Entity should have essential identification information

    Given I do not have any entities
      And I am on the add a new entity page
    When I enter "My Business Relation" in the "Common Name" field
      And I enter "My B.R. Legal Name" in the "Legal Name" field
      And I choose "Corporation" as the "Legal Form"
      And I press "Create"
    Then I should save the entity information successfully

In scenario 1, the user is logged in successfully and the response body
after the 'see the "entities" page' is indeed the entities/index page.

When /should see the "(entities)" page/ do |resource|
  response.body.should =~ /All Entities/m
end

When /on the add a new entity page/ do
  visits new_entity_path
  response.body.should =~ /Add a New Entity/m
end


However, in Scenario 2, I am assuming that a.) the same user (myuser)
and their associated login session is employed.  Since the response body
from this is the login page then evidently this assumption is wrong and
something else is going on.  Can some inform me as to how test logins
are managed/maintained/reused within cucumber/webrat?
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2009-01-12 18:25
(Received via mailing list)
On Mon, Jan 12, 2009 at 10:45 AM, James Byrne <lists@ruby-forum.com>
wrote:
>
> In scenario 1, the user is logged in successfully and the response body
>
>
> However, in Scenario 2, I am assuming that a.) the same user (myuser)
> and their associated login session is employed.  Since the response body
> from this is the login page then evidently this assumption is wrong and
> something else is going on.  Can some inform me as to how test logins
> are managed/maintained/reused within cucumber/webrat?

Each scenario operates in a new session.

I usually have a step that aggregates the login process:

Given /^I am logged in as "(.*)"/ do |role|
  #create a user whose name and role are based on the role
  #log in that user
end

This lets me say:

Given I am logged in as "admin"
When I visit the super-secret page
Then I see it and learn about all its mystery

HTH,
David
171ea139761951336b844e708d1547ab?d=identicon&s=25 James Byrne (byrnejb)
on 2009-01-12 18:46
David Chelimsky wrote:

>
> Each scenario operates in a new session.
>
> I usually have a step that aggregates the login process:
>
> Given /^I am logged in as "(.*)"/ do |role|
>   #create a user whose name and role are based on the role
>   #log in that user
> end
>
> This lets me say:
>
> Given I am logged in as "admin"
> When I visit the super-secret page
> Then I see it and learn about all its mystery
>
> HTH,
> David

Thanks David, I have something like that:

When /user named "(.*)" logs in/ do |name|
  # assumes that the user given exists of course
  visits root_path
  UserSession.find.destroy if UserSession.find
  Then "enter the username \"#{name}\""
  Then "enter the password \"#{name}-password\""
  Then "press the login button"
  Then "welcome message"
end

But this seems needlessly expensive given that the entire application is
secured.  Is there no way of preserving a login session for any
arbitrary period across both features and scenario?  Is there a
technical or philosophical reason why this is not so?
0be0e4aa42aacd9a8a95c792de273ca7?d=identicon&s=25 Aslak Hellesøy (aslakhellesoy)
on 2009-01-12 19:29
(Received via mailing list)
On Mon, Jan 12, 2009 at 6:21 PM, David Chelimsky
<dchelimsky@gmail.com>wrote:

> >    Then they should see the "entities" page
> >    Then I should save the entity information successfully
> >  response.body.should =~ /Add a New Entity/m
>
And coupling scenarios (or any kind of automated test - regardless of
framework) is a very bad idea.

Aslak
171ea139761951336b844e708d1547ab?d=identicon&s=25 James Byrne (byrnejb)
on 2009-01-12 19:47
Aslak Hellesøy wrote:
> On Mon, Jan 12, 2009 at 6:21 PM, David Chelimsky
> <dchelimsky@gmail.com>wrote:
>
>> >    Then they should see the "entities" page
>> >    Then I should save the entity information successfully
>> >  response.body.should =~ /Add a New Entity/m
>>
> And coupling scenarios (or any kind of automated test - regardless of
> framework) is a very bad idea.
>
> Aslak

I do not have a problem with putting :

  Given I am logged in as "myuser"

At the start of every scenario, but is there no way of performing the
actual log in once, place the session info into an instance variable and
then use that rather than actually starting up a new session each and
every time?
994e42bda994be2cd1d791f18ee6d561?d=identicon&s=25 Stephen Eley (Guest)
on 2009-01-12 20:32
(Received via mailing list)
On Mon, Jan 12, 2009 at 1:47 PM, James Byrne <lists@ruby-forum.com>
wrote:
>
> At the start of every scenario, but is there no way of performing the
> actual log in once, place the session info into an instance variable and
> then use that rather than actually starting up a new session each and
> every time?

Sure.  You could mock out your session or deserialize a saved session
object in a Cucumber Before block on every feature except the one that
tests login.  Or put the "Given" call that does the real session
initiation inside a Before so you don't have to look at it every time.
 If you want it to happen _everywhere_, you can also have a Before in
the env.rb file.  You can't chain the results from one scenario to
another, however, because the order scenarios run in (or whether they
run at all) is not guaranteed.  So you'd have to put it in your setup
code.

On acceptance testing, I'd favor going through the actual session
creation logic instead of mocking it, even if you don't put an
explicit "Given" every time.  Yeah, it's slower.  But acceptance tests
aren't _supposed_ to be fast; they're supposed to demonstrate real
usage, and be the last line of defense between your app and the big
bad world.  They're going to be slow with or without login each time.
And if there is some unseen routing or filtering bug in some
controller's session access that doesn't show up in your test because
you skipped past all that, and you lose a day and some hair trying to
figure it out, you're going to wonder whether the seconds you saved
were worth it.


--
Have Fun,
   Steve Eley (sfeley@gmail.com)
   ESCAPE POD - The Science Fiction Podcast Magazine
   http://www.escapepod.org
171ea139761951336b844e708d1547ab?d=identicon&s=25 James Byrne (byrnejb)
on 2009-01-12 20:49
Stephen Eley wrote:

>
> On acceptance testing, I'd favor going through the actual session
> creation logic instead of mocking it, even if you don't put an
> explicit "Given" every time.  Yeah, it's slower.  But acceptance tests
> aren't _supposed_ to be fast; they're supposed to demonstrate real
> usage, and be the last line of defense between your app and the big
> bad world.  They're going to be slow with or without login each time.
> And if there is some unseen routing or filtering bug in some
> controller's session access that doesn't show up in your test because
> you skipped past all that, and you lose a day and some hair trying to
> figure it out, you're going to wonder whether the seconds you saved
> were worth it.

Ok, Ok, Ok... It is no big deal to login in every time.  If that is the
way it should be done in general then I have learned enough these past
weeks that I will go with the flow and save myself some headaches.

Thanks for the pointers and the explanations.  I feel much more
comfortable about doing the login in each scenario now that I understand
the reasons.
42172acdf3c6046f84d644cb0b94642c?d=identicon&s=25 Pat Maddox (pergesu)
on 2009-01-13 02:31
(Received via mailing list)
On Mon, Jan 12, 2009 at 11:49 AM, James Byrne <lists@ruby-forum.com>
wrote:
>> controller's session access that doesn't show up in your test because
> the reasons.
Well you can inject it right into the session instead of doing the
full webrat thing.  That'll definitely cut down on the time it takes.

btw, I know it seems like you want this stuff to persist between
scenarios, but you really don't.  You want to ensure that the world is
in a known state before the test run, so that your tests are
repeatable and reliable.  Getting it into a known state requires two
steps, basically

(1) get to a base state that works for EVERY SINGLE TEST. This
basically means an empty database, potentially populated with some
seed data (like if you store references to zip codes in the db)
(2) at the beginning of each test, modify the state to suit that test.
 You should be changing only the state that you need to write an
expressive test, and no more

If you need to reuse logic, take advantage of one of the existing
reuse patterns.  In cucumber's case, that means extracting code to a
step and calling that in the scenarios.  With RSpec, you've got a bit
more stuff like nested groups with a before block (which imo is NOT a
good idea for cucumber, nesting scenarios would be insane).  What
you're asking about is implicit coupling, and that's not an effective
reuse pattern :)

Pat
This topic is locked and can not be replied to.