Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multiple clients (multiple Session) #15

Closed
julesbou opened this issue May 12, 2011 · 49 comments
Closed

multiple clients (multiple Session) #15

julesbou opened this issue May 12, 2011 · 49 comments

Comments

@julesbou
Copy link

For example : given client A do an action, and client B do an action then client A do another action

@everzet
Copy link
Contributor

everzet commented May 12, 2011

Session is a simple abstraction for the driver. So, what we really need is a:

  1. Support for multiple drivers of single type
  2. Support for switching between drivers inside scenario

Good news is we already have support for part 1 :-)
All we need is abstraction step for driver-switching inside scenario. Something like:

<?php
$steps->Given('/^(?P<step>.+) with (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
    $world->getMink()->switchToDriver($driver);
    $steps->Given($step);
});

This way we will be able to do insane deeds like:

Given I am on /news with goutte1
And I am on /users with goutte2
When I go to /homepage with goutte1
Then ...

What do you think?

@julesbou
Copy link
Author

Very good idea. But a step like this may create lot of ambiguous steps.

maybe :

<?php
$steps->Given('/^(?P<step>.+) with client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
    $world->getMink()->switchToDriver($driver);
    $steps->Given($step);
});

@everzet
Copy link
Contributor

everzet commented May 12, 2011

Yeah, agree ;-)

@julesbou
Copy link
Author

Now we have redundant steps, see : https://github.com/gordonslondon/Mink/commit/99a4aba97c2db0dab6c55db6d5abc3b8838bd8db

what do you think ?

EDIT : is it normal that these steps are redundant ?

for example this code should not throw a Redundant exception :
(because it's not the same step, no ?)

<?php
$steps->Given('/^(?P<step>.+) with client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
    $world->getMink()->switchToDriver($driver);
    $steps->Given($step);
});
$steps->When('/^(?P<step>.+) with client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
    $world->getMink()->switchToDriver($driver);
    $steps->When($step);
});

@everzet
Copy link
Contributor

everzet commented May 13, 2011

You don't need steps for all step types. Behat does not differentiate Given|When|Then|And|But steps, YOU should!
It means, that even if step is defined as Given, you still be able to call it with When or even Then keyword and all localized equivalents ;-)

@julesbou
Copy link
Author

a step like this might create ambiguous steps :

<?php
$steps->When('/^(?P<step>.+) with client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
    $world->getMink()->switchToDriver($driver);
    $steps->When($step);
});

this one work, is it a good idea ? :

<?php
$steps->When('/^"(?P<step>.+)" with (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
    $world->getMink()->switchToDriver($driver);
    $steps->When($step);
});

@everzet
Copy link
Contributor

everzet commented May 13, 2011

How about ? :

When I am on /news in browser goutte1
And I click "downloads" in browser goutte2

This one looks more natural to me, imo.

@marijn
Copy link

marijn commented May 13, 2011

I prefer client over browser, it seems a more accurate description.

@mmoreram
Copy link

And how about adding akinf of tag ( like #goutte1 ) at the end of the string? like:


When I am on /news ~goutte
and on each rule, add this piece at the end with optional instance...

@everzet
Copy link
Contributor

everzet commented May 13, 2011

Ok, now i think i understand possible ambigious steps. We need stable regex to be sure, that it will always much what it have to. So i propose:

<?php
$steps->When('/^(?P<step>.+) in mink:(?P<driver>.+) client$/', function($world, $driver, $step) use($steps) {
    $world->getMink()->switchToDriver($driver);
    $steps->When($step);
});

This way, we will be able to write something like:

When I am on /news in mink:goutte1 client
And I click "downloads" in mink:goutte2 client

This way we remove possible ambiguity and add possibility to write user-defined session steps. What do you think, guys?

It's kinda strange by first. But it solves problem and adds additional information layer on top of our steps without harming the humanability and readability of steps.

@marijn
Copy link

marijn commented May 13, 2011

I think this will make Gherking look and feel too technical for business people working with it.
I prefer to keep it simple in Gherkin over having it simple in PHP.

@everzet
Copy link
Contributor

everzet commented May 13, 2011

@mmoreramerino interesting idea but, in this case, we lose readability in our steps, transforming them to another programmin language, which is bad turn for Gherkin and Behat, imo.

@everzet
Copy link
Contributor

everzet commented May 13, 2011

@marijn you're talking about @mmoreramerino proposal or mine?

@ThePixelDeveloper
Copy link
Contributor

We shouldn't need to modify the steps for this to work, I'd like to see it done with tags or at a higher level. Speaking of tags; Is it possible to apply them to steps?

@browser1
  When I am on /news
@browser2
  Then I should see "browser1 has visited this page"

Thanks for the email everzet.

@everzet
Copy link
Contributor

everzet commented May 13, 2011

@ThePixelDeveloper tags are allowed only on scenarios, outlines and features in Gherkin DSL specification. And i don't want to break Gherkin specs. It's very readable and clean now. We'll make it only worse.

@everzet
Copy link
Contributor

everzet commented May 13, 2011

@ThePixelDeveloper also, i think we should modify steps, cuz steps should tell reader about what type of interaction they actually describe. Tags are just meta information for filtering, hooking and categorizing. They doesn't tell reader anything useful about scenario itself, but steps should!

When you describing in your scenario communication between 2 clients, then you should talk about two clients in your steps!

@ThePixelDeveloper
Copy link
Contributor

Then with each feature your regular expression becomes more and more complicated. From my point of view When I am on /news should not know about the browser it's being run by, that's my point.

Now reading back, your regular expression above does what I suggest.

@everzet
Copy link
Contributor

everzet commented May 13, 2011

@ThePixelDeveloper yes, we're not talking about initial step definitions change, but about adding new one with inline step-to-step call!

It's great demonstration of Behat extensibility, by the way ;-)

@marijn
Copy link

marijn commented May 13, 2011

Perhaps we're going the wrong way about this. I'm clueless about Behat internals so perhaps this is not possible but why not:

 When I am on /news
Using client goute
  And I click "downloads"
Using client alternative-goute

@marijn
Copy link

marijn commented May 13, 2011

Aside from the fact that it's not in cucumber...

@everzet
Copy link
Contributor

everzet commented May 13, 2011

It's possible, but NO!

It will break translations, readability and many other good things.

@marijn
Copy link

marijn commented May 13, 2011

Just spitballing :-)

I'm just not particular in favor of mink:client-name but I can see that alternatives aren't any better...

@everzet
Copy link
Contributor

everzet commented May 13, 2011

Agree. I don't like this mink: part too

@marijn
Copy link

marijn commented May 13, 2011

From a natural language perspective putting it in braces might make sense:

Given I am on /news (with goute)
  And another user is on /news/delete (with goute-alternative)

@everzet
Copy link
Contributor

everzet commented May 13, 2011

with doesn't makes sense:

Given I am on ... with ...

and what's even worse:

Given I fill in username with "everzet" (with goutte)

maybe

Given I am on /news (in goutte client)
And I am on /articles (in goutte-alternative client)

@marijn
Copy link

marijn commented May 13, 2011

You're right. Your suggestion to use in sounds good to me though. Within braces that is.

@cbandy
Copy link

cbandy commented May 13, 2011

What does the regex have to do with anything? People will use whatever language makes sense in their application.

The feature being requested is a way to change the "current session" from within a step.

@everzet
Copy link
Contributor

everzet commented May 13, 2011

@cbandy please, read thread carefuly, before posting your get a life-comments:
Mink already supports this feature. The request and conversation is about using this feature in Behat steps by not breaking already existing ideology and defined in future user steps.

@cbandy
Copy link

cbandy commented May 13, 2011

I didn't realize Mink already supports switching sessions. @everzet's first comment seemed to imply that it does not:

\2. Support for switching between drivers inside scenario

What I gathered from reading the thread is that there isn't a clear, natural way to describe "which session" to which a rule applies. In my opinion, awkward language should be a compromise made by the users of your library, not one that is forced upon them.

@everzet
Copy link
Contributor

everzet commented May 13, 2011

@cbandy awkward language? Gherkin? Please, try to throw away your scepsis and read this thread again, but from different point. What we're trying to do here is a simple way to switch between 2 or more browsers in single Behat scenario. Default, but not forced way. You can already do it by yourself, but it's common case to have clean out-of-the-box solution.

Behat is already awesome enough to happily use it, even without bundled with Mink web steps, without Sahi or Mink itself. But Mink does comes with Mink, Sahi integration and optional bundled steps, which newcomers can set up and use in matter of seconds. That's what i'm trying to achieve with Behat and Mink - to build very-useful libraries, that you can simply install and use very fast and very easy!

Yes, there's no yet clear natural way to describe which session to which step applies. And we're trying to find it. So, what's your point?

@julesbou
Copy link
Author

this one works and doesn't seems ambiguous:

<?php
$steps->When('/^(?P<step>.+) in client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
    $world->getMink()->switchToDriver($driver);
    $steps->When($step);
});

EDIT

I think this one is ambiguous:

Given I am on /news (in goutte client)

with this step :

<?php
$steps->Given('/^(?:|I )am on (?P<page>.+)$/', function($world, $page) {
    $world->getSession()->visit($world->getPathTo($page));
});

@everzet
Copy link
Contributor

everzet commented May 14, 2011

I'm thinking now about changing abstractions little bit. Switching driver, when you need to switch a session looks kinda stupid. Also, i'm pretty sure Mink will have easy configuration mechanics for sessions/drivers for multi-session testing. But i'm not sure about bundled step by 2 reasons:

  1. It still can bring some ambiguity in some cases and we don't know where
  2. It's very easy to write it by your own, when you need it (only 4 lines of code)

@everzet
Copy link
Contributor

everzet commented May 14, 2011

@gordonslondon no it's not. Parens are not part of regex - it's just matcher ;-)

@halfnelson
Copy link

It still can bring some ambiguity in some cases and we don't know where
It's very easy to write it by your own, when you need it (only 4 lines of code)

I agree whole heartedly. Just put the best example you came up with in the docs so people KNOW they can do this, and away they go.
Personally I will be using something like "Given visitor "david" is on the homepage" and just ensure that I do not write ambiguous test cases. My step code will create a driver/session for david if it doesn't exist or fetch the current one if it does; then run the step.

@everzet
Copy link
Contributor

everzet commented May 16, 2011

Hey guys, i'm glad to announce, that i've removed driver word from almost every part of Mink API (except drivers part itself, of course ;-) ). Now you work with sessions, which is more logical conception and make lot more sense in terms of multi-session support and readability of tests. Now you can really write multi-sessional tests with beautiful api ;-)

You can see changes in https://github.com/Behat/Mink#readme example ;-)

@cordoval
Copy link

why is this issue still open?

@everzet
Copy link
Contributor

everzet commented Jul 22, 2011

@cordoval it waits Behat cookbook article "How to write multisessional Mink scenarios" ;-)

@cordoval
Copy link

maybe i misread the whole thread or do not understand but is this not already supported by putting @mink:sahi or other? on each scenario?

also i was in addition thinking on finding a way to assert methods, actions, and controllers for a sf2 app on behat ContexFeature

@stof
Copy link
Member

stof commented Jul 24, 2011

@cordoval the @mink:sahi tag is about changing the default session for a scenario. The current thread is about using multiple sessions in the same scenario.

And you should not assert controllers or action: it is not part of the behavior that can be observed by the user but of the internal implementation

@cordoval
Copy link

Thanks @stof, just went over it again and realized that the support was there all along:

// mix sessions
$mink->getSession('goutte1')->getPage()->findLink('Chat')->click();
$mink->getSession('goutte2')->getPage()->findLink('Chat')->click();

However the only problem was how to do this on a single line from steps...

So i guess that is still not fixed exemplified yet? @everzet

I would like to write the cookbook entry however, i don't see any examples yet on steps that are fixed

also I ran into weird problems when reseting when logging within a scenario, the next scenario (using FOSUB) would appear to have been already logged in. The sahi browser would reset on and off several times, it is not very great really but the only option to use when javascript is present... well so besides experimenting I ran into several problems that i half solved.

Anyway, thanks just wanted to comment and follow up with this development.

@stof
Copy link
Member

stof commented Jul 25, 2011

@cordoval write a step to logout the client. It is easy as the only need is to visit the logout page

@schmittjoh
Copy link
Contributor

I have the following hook to isolate the sessions as much as possible (note that this might come at a performance penalty for running your tests):

<?php
    /**
     * @AfterScenario
     */
    public function stopSessions()
    {
        $mink = $this->getMink();
        $mink->stopSessions();
        $this->registerSessions($mink);
    }

@everzet
Copy link
Contributor

everzet commented Jul 25, 2011

@schmittjoh you don't need to stop/start sessions manually, cuz there's awesome:

$mink->restartSessions();

method in Mink 1.x: http://mink.behat.org/#resetting-the-session ;-)

@everzet
Copy link
Contributor

everzet commented Jul 25, 2011

Also, there's much cleaner *.feature-way to do this:

@insulated
Feature: ...
  ...

All scenarios in such feature will be insulated :-)

@schmittjoh
Copy link
Contributor

Yeah, I think these methods weren't available when I wrote the code, but I'll check them out :)

@cordoval
Copy link

so the example is a chat between two users or a manager and a client I see hmm yeah interesting, i will have to write these kind of scenarios at some point too, mostly for an admin and a regular user of an app.

When @cordoval fills in "textarea" with "want to write the cookbook entry" (in sahi1)
When @cordoval clicks on "Comment" (in sahi1)
When @everzet clicks on "notification" (in goutte1)
Then @everzet will read somewhere "want to write the cookbook entry" (in goutte1)

so the idea is that for some things we need sahi for the javascript fanciness and then goutte for speed?
Else if not what is the use of this? What other scenarios could be out there?

@everzet
Copy link
Contributor

everzet commented Jul 30, 2011

@cordoval interaction of two users on site. Sometimes it might be useful. For example, when user A does some things, which should change the context of user B.

@ctrahey
Copy link
Contributor

ctrahey commented Aug 11, 2013

Hi Folks, interesting discussion. I've been thinking about this a lot, and I use Behat in stakeholder-facing places as often as possible, so I had a big interest in getting the "implementation details" out of the gherkin (read: we shouldn't require the driver name to appear in the gherkin) as well as not needing to rewrite all step definitions to be session-name aware.

Check out this comment: https://github.com/Behat/Mink/pull/368#issuecomment-22445924
for a sample step-definition that (together with that PR) gives a very stakeholder-friendly way to accomplish this --AND -- to make use of all available step definitions (no need to rewrite them all to be multi-persona aware).

The end result is acheived through a "session-switching" step, which I have suggested be formatted as:

Given I adopt the persona "John Doe"

The "persona" word is very stakeholder friendly, and the name you use is purely arbitrary and becomes the name of the Mink session, which means you can switch back and forth between personas and still be using the same session per person. Example in the linked comment.

@ftassi
Copy link

ftassi commented Aug 13, 2013

👍 I'm doing it quite in the same way, A step like

Given I adopt the persona "John Doe"

or even

Given "John Doe" is browsing

sounds good to me and making the new session the default one (as in #368 ) is really a good way to reuse existing steps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests