This tutorial has a new version, check it out!

BDD, Behat (version 2.5), Mink and other Wonderful Things

1:14:43
Buy Access

If you own this tutorial and want to upgrade to the latest Behat 3 version, send us an email/contact message and we'll be happy to give you a coupon code to order the 3.0 version absolutely free :). Yay upgrading!

Ready to revolutionize how you develop? In this tutorial, you'll internalize Behavior-Driven Development and how thinking about behavior will increase the quality and efficiency of your code. You'll become an expert in Behat - the BDD PHP framework - and Mink - your key to testing web applications in sophisticated ways that include the ability to test your JavaScript pages. We'll also explore the pitfalls of testing with Behat, such as data sanitization, bootstrapping your code, and other challenges. By the end, you'll be well on your way to writing high-quality tests for your application and - more importantly - approaching development in a totally new light.

Behat works great with any PHP project, but if you're using Symfony2, we'll give you some special tips to get you rolling.


Your Guides

Ryan Weaver Leanna Pelham

Questions? Conversation?

  • 2017-06-13 Victor Bocharsky

    Hey Jon,

    Hm, weird error, I don't have many ideas. Try to check any new updates for Selenium server and FireFox. Also, could you try to restart your Mac and try to run tests again? If it doesn't work, try to start selenium server with sudo, maybe you have permissions issue. Btw, what version of Behat do you have? Could you try to upgrade it too?

    Cheers!

  • 2017-06-12 Jon Robinson

    Hi, thanks for this... you guys have the best Behat/Mink tutorials.

    Question though... when using @javascript in my feature file... Firefox loads and runs the tests successfully, which is great, using Firefox version: 47.0. However, I've recently updated to latest Firefox (53.0). Every time I run my tests now, Firefox loads, but the url from Given I go to "http://whateversite.com" is not entered and obviously nothing happens and eventially the test timeouts with error: Could not open connection: Failed to connect to binary FirefoxBinary(/Applications/Firefox.app/Contents/MacOS/... on port 7055; process output follows: "

    Any ideas why? I am using latest selenium-server-standalone-3.4.0

    Thanks in advance,
    Jon

  • 2017-04-26 Victor Bocharsky

    Hey Andrew,

    I suppose your scenario has \@javascript tag and Behat trying to run it on Selenium server. But this error means that you do not start Selenium server yet. Take a look at: https://knpuniversity.com/s... - which explain how to run Selenium server.

    Cheers!

  • 2017-04-25 Diego Aguiar

    Hey Andrew!

    Look's like you are missing the starting curly brace and a couple of comas
    This is how it should looks like (feel free to copy and paste it into your code, I just reformatted it)


    {
    "name": "andrew.pang2/goku_automation",
    "description": "Andrew automation suite",
    "require": {
    "behat/behat": "^3.3",
    "behat/mink": "^1.7",
    "behat/mink-selenium2-driver": "^1.3",
    "behat/mink-zombie-driver": "^1.4",
    "behat/mink-browserkit-driver": "^1.3",
    "behat/mink-goutte-driver": "^1.2",
    "behat/mink-extension": "*"
    },
    "minimum-stability": "dev",
    "config": {
    "bin-dir": "vendor/bin/",
    "authors": [
    {
    "name": "andrew.pang2",
    "email": "andrew.pang2@workday.com"
    }
    ]
    }
    }

    Cheers!

  • 2017-04-25 Andrew Pang

    "name": "andrew.pang2/goku_automation",
    "description": "Andrew automation suite",
    "require": {
    "behat/behat": "^3.3",
    "behat/mink": "^1.7",
    "behat/mink-selenium2-driver": "^1.3",
    "behat/mink-zombie-driver": "^1.4",
    "behat/mink-browserkit-driver": "^1.3",
    "behat/mink-goutte-driver": "^1.2"
    "behat/mink-extension": "*"
    },
    "minimum-stability": "dev",
    "config": {
    "bin-dir": "vendor/bin/"
    "authors": [
    {
    "name": "andrew.pang2",
    "email": "andrew.pang2@workday.com"
    }
    ]
    }

  • 2017-04-25 Andrew Pang

    "name": "andrew.pang2/goku_automation",
    "description": "Andrew automation suite",
    "require": {
    "behat/behat": "^3.3",
    "behat/mink": "^1.7",
    "behat/mink-selenium2-driver": "^1.3",
    "behat/mink-zombie-driver": "^1.4",
    "behat/mink-browserkit-driver": "^1.3",
    "behat/mink-goutte-driver": "^1.2"
    "behat/mink-extension": "*"
    },
    "minimum-stability": "dev",
    "config": {
    "bin-dir": "vendor/bin/"
    "authors": [
    {
    "name": "andrew.pang2",
    "email": "andrew.pang2@workday.com"
    }
    ]
    }

  • 2017-04-25 Andrew Pang

    I am using wiki/main page to do a search and following your examples in the tutorial gave me this error:
    Scenario: Search for a word that exists # features/search.feature:7
    Given I am on "/wiki/MainPage" # FeatureContext::visit()
    Could not open connection: Curl error thrown for http POST to http://localhost:4444/wd/hub/session with params: {"desiredCapabilities":{"tags":["apang2-08","PHP 7.0.17"],"browser":"firefox","ignoreZoomSetting":false,"name":"Behat feature suite","browserName":"firefox"}}

    Failed to connect to localhost port 4444: Connection refused (Behat\Mink\Exception\DriverException)

  • 2017-04-17 Diego Aguiar

    Hey Andrew!

    If you are using MinkContext, then you can use "print last response" step in your features, so you can check how looks like the HTML for the page you currently on. In your case you need to check what's the name of the search field in wiki main page

    Cheers!

  • 2017-04-17 Diego Aguiar

    Hey Andrew!

    JSON format is very picky, I think you are missing a "closing curly brace" but, could you show me how your composer.json file looks like ?

    Cheers!

  • 2017-04-14 Andrew Pang

    Anyone can tell me why I am getting this error:

    composer require --dev behat/behat behat/mink-extension behat/mink-goutte-driver behat/mink-selenium2-driver

    [Seld\JsonLint\ParsingException]
    "./composer.json" does not contain valid JSON
    Parse error on line 1:
    "name": "andrew.pang2/goku
    ---------^
    Expected one of: 'EOF', '}', ',', ']'

  • 2017-04-14 Victor Bocharsky

    Hey Andrew,

    Yeah, Behat with Selenium do the trick. You can even test JS websites with this bundle, just add @javascript above your scenarios.

    Cheers!

  • 2017-04-13 Andrew Pang

    apang7@gmail.com, I am looking for automation on websites. Seems like behat will do the job

  • 2017-04-12 Andrew Pang

    Is there a list of keywords or objects to understand the functions of these?

  • 2017-04-12 Diego Aguiar

    Hey Andrew!

    Try changing "searchTerm" by only "search", remember that behat will look up for any input field (id, name, label or value) that matches that text

    Cheers!

  • 2017-04-11 Andrew Pang

    I try to follow your example on searchTerm on a different website (wikipedia) but failed. Here is the error:

    Scenario: Search for a word that exists # features/search.feature:6
    Given I am on "/wiki/MainPage" # FeatureContext::visit()
    When I fill in "searchTerm" with "Velociraptor" # FeatureContext::fillField()
    Form field with id|name|label|value|placeholder "searchTerm" not found. (Behat\Mink\Exception\ElementNotFoundException)

  • 2017-04-11 weaverryan

    Yo @disqus_EwCSvPkx4r!

    Great question :). Let me give you a quick run-down of what we do here at KnpUniversity:

    1) Obviously, we use Behat. This is probably our main tool, because ultimately we're concerned most about the *behavior* of the features we're building. If the feature has any decent complexity, we'll cover it with a Behat scenario (and often, when we build a new big feature, we'll add the features/scenarios first)

    2) When we're building a feature, we might find out that a specific function is quite complex. We *could* write several Behat scenarios to cover the different input/output of that function, but it would be easier if we tested the function (unit) directly. In this case, we'll use PhpUnit (we don't [yet] use PhpSpec, but that's also a great tool for this).

    3) But wait! Sometimes when you're unit testing that complex function, you realize that if you mock all the dependencies, all the complexity is gone! For example, if a function makes a complex database query and then uses that output to call 4 other services... then once you've mocked all of that out... there is really no "meat" left in your test. In this cases, it's better to do an integration test: a PhpUnit test where you boot the container and actually use your *real* service (and so also, your real database connection). This is a *great* way to test big "units" of your code. Of course, those tests are slower and you need to worry about setting up your database - i.e. making sure that specific tables have specific records in them to support your test. Btw, I don't typically load my fixtures in tests (the same is true for Behat tests) - usually I just make sure that whatever tables I'm concerned with have specific data in it.

    So, Behat & PhpUnit, but I use PhpUnit for both unit tests, and less pure (but super pragmatic) integration tests.

    Cheers!

  • 2017-04-07 Martin Bittner

    So Behat is to do integration testing, to make sure everything fits and works together.
    Do you still use phpunit to test your model?
    Would you mind explaining your overall testing strategy / organization. What are all the components (phpunit, behat, alice, etc) you use and how do you use them.
    Thanks

  • 2017-02-13 Victor Bocharsky

    Thanks for sharing this!

    Cheers!

  • 2017-02-11 Fabien Huitelec

    I would just add as a reference for others looking for a quick solution running chrome-driver:
    When running the selenium server, specify it to be run with the chrome driver:

    java \
    -Dwebdriver.chrome.driver="chromedriver" \
    -jar selenium-server-standalone-3.0.1.jar

    (at the same root of chromedriver and be careful of the selenium server version)

  • 2016-11-07 weaverryan

    Awesome! Great news - glad it all got finally fixed. I think things are a little weird right now with the v 3 of the Selenium Server being released - things seem to be a bit more "broken" than normal.

  • 2016-11-07 Syed Abouzar Mehdi

    @weaverryan fixed it finally with Latest Chrome driver https://chromedriver.storag...
    meanwhile i was working on some FeatureContext working with Ajaxcalls.. Thanks Again =) cheers

  • 2016-10-26 weaverryan

    Hmm, I'm not sure - it's definitely some issue then with Selenium and possibly your system. I did find an issue that has the same error - it seems very hard to reproduce: https://bugs.chromium.org/p.... Some of the suggestions include making sure you have enough memory (only really relevant if you're doing something in Docker or similar, as the person was) and also a "--disable-impl-side-painting" flag. You can see how to set flags for Chrome here: https://edmondscommerce.git... (look for chromeOptions, then args). I don't do this very often, so I'm not sure if it'll help - just trying to throw it out there!

    For other browsers, it depends on your system, but you can check out the plugins here: http://www.seleniumhq.org/d...

    Sorry I can't help more - usually the solution is upgrading... but sometimes Selenium might need a bit more help.

    Cheers!

  • 2016-10-26 Syed Abouzar Mehdi

    ya this is the problem now how to overcome it. my selenium and chromes are latest but still having issues.. I dont know how to fix these.. Firefox having same issues as well.. what other browser I can use ? and how ..
    thanks for the help

  • 2016-10-25 weaverryan

    Hey Syed!

    Hmm, when this type of thing happens to me (which is rare, but it occasionally happens), I always update the selenium server to the latest version. What happens is that Chrome will receive an update, and it will break something that Selenium relies on. Then, Selenium will release an update to fix the change in Chrome. So, hopefully updating Selenium will fix that. Also, there is a "Chrome Driver" that I believe you also need to have running (you may or may not have this - I'm not 100% sure if it's required), but I would try updating that as well.

    Let me know if that helps!

  • 2016-10-25 Syed Abouzar Mehdi

    Seleniumversion is: selenium-server-standalone-3.0.0-beta3.jar

  • 2016-10-25 Syed Abouzar Mehdi

    @bocharsky25 hi !! i am facing a new issue from yesterday.. whenever i run any feature file i get following error . It came at once things were fine but now chrome starts and gets closed instantly... any Help?
    --------------------
    no such session
    (Driver info: chromedriver=2.23.409699 (49b0fa931cda1caad0ae15b7d1b68004acd05129),platform=Windows NT 10.0.10240 x86_64) (WARNING: The server did not provide any stacktrace i
    nformation)
    ----

  • 2016-10-03 Victor Bocharsky

    Hey Syed,

    It's difficult to say what's the problem here. BTW, if you use basic HTTP auth only locally (or for testing) but traditional login form on prod - that's a bad idea. You should test the same things which you use in production.

    Yes, you can! Check MinkContext one more time - it has something like "I check ...", "I uncheck ...", "I select ... from ...", etc. But having problems with ` --append-snippets` is odd. Actually, you don't need to use ` --append-snippets`, just write a new step in any feature (*.feature) and run Behat. Behat generate this step definition (i.e. a new method definition) and show you it in console. Then you can manually copy it and past in the proper feature context.

    Cheers!

  • 2016-09-30 Syed Abouzar Mehdi

    tried but dont knw whats the issue it does not work :/ it stuck on this http authentication.... thinking to remove the http authentication from my local dev.
    Secondly I am just using scenarios to follow my instructions(features) not adding anything in FeatureContext.php so far so good. Because whenever i try to --append-snippets then i start getting thousands of errors :/
    Now my question is can i use drop downs/checks/selects via scenarios only ?

  • 2016-09-29 Victor Bocharsky

    Hm, if you follow the URL like `http://username:password@ex... ` with correct credentials - you won't be asked for http auth at all, you just should be redirected to the domain specified in previous URL (it's `http://example.com/ `). Are you sure your http auth works properly?

  • 2016-09-29 Syed Abouzar Mehdi

    another thing what should i do if it asks for http auth twice. first before login and once after login...

  • 2016-09-28 Victor Bocharsky

    Hey Syed,

    Use next URL pattern:
    http://username:password@example.com/

    Cheers!

  • 2016-09-28 Syed Abouzar Mehdi

    @bocharsky25 how to do http authentication?
    i dont understand how to write in base_URL domain:username:password ? can you tell me the exact scenarior

  • 2016-09-22 Syed Abouzar Mehdi

    thanks fixed this one

  • 2016-09-22 Victor Bocharsky

    I think I know the problem, since you already extends MinkContext in your FeatureContext - you can't specify MinkContext in your behat.yml config file. Keep the only FeatureContext there:

    default:
    suites:
    defaults:
    contexts:
    - FeatureContext

    I bet that's the problem.

  • 2016-09-21 Syed Abouzar Mehdi

    hey @bocharsky25 m so stuck :/
    now i removed "FeatureContext::iAmOnHomepage()" from my FeatureContext but its still showing old message again.

  • 2016-09-21 Victor Bocharsky

    Hey Syed,

    MinkContext already has defined this step, check it here. That's why Behat do not allow you to define it again. You should remove your "FeatureContext::iAmOnHomepage()" method or do not use MinkContext.

    Cheers!

  • 2016-09-21 Victor Bocharsky

    You're welcome!

    BTW, one more useful command which helped me a lot when I had discovered it: $ behat -dl and $ behat -di - which print all available step definitions. I think it might be useful for you too.

    Cheers!

  • 2016-09-21 Syed Abouzar Mehdi

    @bocharsky25 check my yml/composer/feature files http://pastebin.com/LM7uDf4Q
    but i am getting errors there.. Can you guide me or tell me what should i write in FeatureContext for my given feature file
    FeatureContext::iAmOnHomepage()
    Behat\MinkExtension\Context\MinkContext::iAmOnHomepage()
    Then I go to "/programs/list"
    Step "/^(?:|I )am on (?:|the )homepage$/" is already defined in FeatureContext::iAmOnHomepage()

  • 2016-09-20 Syed Abouzar Mehdi

    @bocharsky25 thanks man , I got it what you said. let me try to extend my FeatureContext with Mink and try to run it. will hit you in a while if i get stuck in something :D

  • 2016-09-20 Victor Bocharsky

    Hey Syed,

    I can help you with your questions:
    1. The --init command tells Behat to provide you with things missing to start testing your feature. In your case - it’s probably a FeatureContext class under the features/bootstrap/FeatureContext.php file. That's it. If you already have this files - nothing will happen if you run this command again. Run $ behat --append-snippets if you want Behat to add missing steps to the main context itself or $ behat --append-to=APPEND-TO to append missing steps to the specified context file. Check more information about available commands with $ behat --help.
    2. Actually, it happens due to your *empty* FeatureContext extends default feature context which already has some pre-defined steps. Probably you extend MinkContext, but it depends on your actions. So for example, open MinkContext in your code editor and you will see this pre-defined steps there.

    Cheers!

  • 2016-09-19 Syed Abouzar Mehdi

    @weaverryan i have few questions things are confusing as
    1: Once i have created feature file and feature.context can I edit my feature file and run --init again! to recreate featurecontext with my modified Feature file? ( as I tried it but nothing happens)
    2: Another thing sometimes when i do new installation. i just write the feature file and everything works fine without writing a single word to FeatureContext. how this works actually? what my scenario was to visit a website and login there and then go to another sub page from given link! and it worked perfectly without writing a single code in FeatureContext!

  • 2016-09-15 weaverryan

    Hi Miya!

    Definitely :). We *usually* include detailed install instructions in the README in the download, but it looks like we forgot to add those this time! Shame on us! I've just updated the README file with details - you can see it here: https://github.com/knpunive.... I'm deploying that to the code download right now.

    If that doesn't answer all of your questions, please let me know!

    Cheers!

  • 2016-09-14 Miya

    Hey I have a question. Do you know how to setup the database in order to run these scenarios?

  • 2016-09-12 weaverryan

    Yep, I've had the same issues at times. What happens is that a browser releases a new version, and this breaks some backwards-compatibility in Selenium. Sometimes, a new version of Selenium has already fixed the issue, but sometimes that hasn't happened yet. In those cases, exactly like Victor said, I'll switch back and forth between Firefox or Chrome to get one that works. This doesn't happen very often, but it definitely happens :).

    Cheers!

  • 2016-09-09 Syed Abouzar Mehdi

    ya thanks Victor
    i am now starting with this one
    $this->driver = new \Behat\Mink\Driver\Selenium2Driver('chrome');
    $this->session = new \Behat\Mink\Session($this->driver);
    $this->session->start();
    and in behat.yml i am using same as you said../
    now when chrome opens one tab has -> Data; and then other one opens with Data; and later on browses my given URL... :D
    sorry just learning :$

  • 2016-09-07 Victor Bocharsky

    You should specify browser_name in behat.yml configuration for Mink extension, that's it:


    default:
    extensions:
    Behat\MinkExtension\Extension:
    browser_name: chrome
  • 2016-09-07 Syed Abouzar Mehdi

    i tried alot to play with google but gets enough issues in it . Dont know how to make it possible to run tests via google.

  • 2016-09-07 Victor Bocharsky

    Hey Abuzar,

    I had the same issue, that's why I switched to the Google Chrome as a default browser for Behat tests. I suppose it's due to some BC breaks in new version of FireFox.

  • 2016-09-06 Abuzar Mehdi

    @weaverryan i am facing few issues .
    when i run the bin/behat my firefox browser opens with welcome page and nothing happens.
    "about:blank&utm_content=firstrun" <-= in firefox address bar kindly tell me how to fix this one

  • 2016-07-18 Diego Aguiar

    Hey Ryan!
    Thanks for your answer

    I ended doing your solution A ;]

  • 2016-07-15 weaverryan

    Hey guys!

    You're doing the right thing - but you need to use a JavaScript-based driver if you want to do this. The reason is that a button (except for a submit and reset button) has *no* functionality outside of JavaScript. What I mean is: if I click a "submit" button, it submits a form. But if I click your button (in an environment that has no JavaScript), nothing will happen: this button has no native functionality. The Symfony2Extension is basically trying to warn you about this.

    So, solutions:

    A) Don't click this button :). If you're clicking it simply so that a drop-down can open and you can click a link/button that's *inside* of that drop-down, you can simply skip clicking this first button and click/press the "hidden" link/button directly. Of course, you can't do this in a "real browser" (because the link/button is hidden), but you can with the Symfony2Exension - because it's simply parsing the HTML and can click/press any button you want.

    B) Use a JavaScript-based driver (like Selenium).

    Both are good solutions - (A) feels like cheating, but I don't think it is - I'm not worried about testing that the drop-down works, so it's cool to skip it if you want.

    Cheers!

  • 2016-07-15 Diego Aguiar

    Hello Victor

    I just can't imagine why symfony's driver don't support clicking on button tags, but well ... thanks for your reply ;]

  • 2016-07-14 Victor Bocharsky

    Hey Diego,

    In your case I simply replace a button `<button type="button">` tag with a link `<a href="javascript:void(0);">` tag. If you use Twitter Bootstrap - this link will exactly look like a button. But I'm wondering about other solutions here too )

    Cheers!

  • 2016-07-13 Diego Aguiar

    Hey there!
    I found this tutorial really good, I really appreciate your effort doing it.
    Also a I have a question :]

    How do you press a button tag using symfony-extension driver ?
    I'm getting this error over and over(I'm going crazy) - Behat\Symfony2Extension\Driver\KernelDriver supports clicking on links and submit or reset buttons only. But "button" provided

    My step is - When I press "Actions" from MinkExtension class, method pressButton($button)
    And my html is like this:
    <button data-toggle="dropdown" type="button" class="btn btn-default dropdown-toggle">
    Actions
    </button>

    Thanks in advance

  • 2016-03-22 Dan Costinel

    I still experience an error when testing. Do you know why my test fails? http://imgur.com/Ts6E3w1

  • 2016-03-22 Dan Costinel

    Nevermind guys. I've missplaced the security. Instead of putting it in app/config/security.yml, I've placed it in app/config/config.yml... Sorry!

  • 2016-03-22 Dan Costinel

    Hello guys. I copied all the "finish" files into a fresh Symfony 2.7.10 project. I changed few things in your files, in order to make the project work, and I finally did it. Now I'm stuck at login, as I can't login with the provided credentials (user=admin, pass=admin). I've re-created the db with the link inside my app ( /_db/rebuild ) - nothing, I've deleted entirely my db, and I've re-created it with doctrine:database:create, and doctrine:schema:update --force, but still nothing. I get the same error message when I try to login: Invalid credentials. I tried to generate, online, the bcrypt hash for the string "admin" using http://bcrypthashgenerator...., and replacing the password field value within user table, but without any good result. Any ideas on how to solve it, maybe without re-creating all from the start? Thank you!!

  • 2016-01-19 weaverryan

    Hi Bartek!

    Yes, I have done this stuff before with a client (at least with iframes, but I think also with windows) - some of the details are fuzzy, but we were totally able to pull it off. As you probably already know, the key methods are on the Session: https://github.com/minkphp/.... I would use getWindowName() and getWindowNames() (https://github.com/minkphp/... to debug and figure out what all the window names are being called during the process.

    I know that's vague, but I hope it helps! Cheers!

  • 2016-01-19 Bartek

    Hi, How can I switch from one window to another. For example, my scenario is as follows -

    Scenario Outline: User login with Facebook
    When I press "siginFacebook"
    And I switch to the new tab
    And I fill in "<email>" for "email"
    And I fill in "<password>" for "pass"
    And Click the "u_0_2" select by "id"

    In this stage, as facebook login works, so popup window close automatically and it generates an error -
    "Window not found. The browser window may have been closed."

    Do you know how to come back to my original window after a successful facebook login?

  • 2015-10-19 Patrick O'Sean

    Nice, thanks I will have a look at phpspec and your upcoming screencast on it. Regards

  • 2015-10-19 weaverryan

    Hey Patrick!

    Theoretically, I think you've nailed it (though, you should take a look at PhpSpec for unit tests - we'll have a tutorial on that soon). However, I am not a huge fan of unit testing. I mean, yes, I do them - but only when I'm writing a function that "scares" me. In other words, if a function is pretty straightforward, then I rely on my Behat scenarios (tests) to see that the whole system is working. Your 1/2/3 order is perfect, but I would only do 2 when you feel you need to. Though, with PhpSpec, (2) becomes less about "testing" and more about "helping you design your classes", which is worthwhile on its own.

    Cheers!

  • 2015-10-16 Patrick O'Sean

    Hey Ryan, I've read and seen a lot about TDD and BDD now. My question is, how do I start now implementing a new feature. Let's say I have a dvd store and want to be able to add new dvds to the inventar. This process requires maybe different methods. My approach would be:
    [1] Create BDD behat scenario / functional test for adding a new dvd
    [2] Create a unit test with phpunit for each method that is required for adding a new dvd
    [3] Create the actual code for adding a new dvd

    For me, this would be a combination of BDD first and TDD afterwards? Or could you please explain me the correct "theoretical" way if I misunderstood something.
    Regards, Patrick

  • 2015-10-13 weaverryan

    Hey!

    If you own the Behat 2.5 version, shoot us an email/contact message and we'll be happy to give anyone a coupon code to grab the 3.0 version free :).

    Cheers!

  • 2015-10-13 truthrevealer

    Should the owners of Behat 2.5 course purchase this one as well to get access to it?

  • 2015-10-13 Richard Bagshaw

    So much yes!! I want this one :) Behat 3!! :)

  • 2015-07-15 weaverryan

    Hey!

    Yep, I *do* use both: Behat for functional tests and PHPUnit for unit tests. I end up writing mostly functional tests, so I use Behat quite a bit more. That may be how you're feeling as well :).

  • 2015-07-15 Victor Bocharsky

    Hi, Ryan!

    Does it normal to use both PHPUnit and Behat tests in one project? Or better keep up only one testing framework for all tests?
    I started to use Behat and began to wonder why I need a PHPUnit anymore. It seems a bit confused to use them both in one project, doesn't it?

  • 2015-04-13 weaverryan

    Well hi Inna!

    Interesting! So, Behat should be able to "autoload" anything that Composer autoloads (e.g. anything that follows PSR-4 or PSR-0). It looks like you're using this library: https://github.com/hivework..., and so if you bring this in via Composer, then the autoloading should work out of the box. This is exactly how the MinkExtension is loaded too.

    So, are you installing this via Composer? Can you, on some working page in your site (not in Behat), instantiate a new Extension object manually (if you can, then you should be able to reference it in behat.yml).

    Cheers!

  • 2015-04-13 Inna

    Hi All!

    I'm trying to use BusinessSelectorExtension. I add to behat.yml file:

    extensions:
    OrangeDigital\BusinessSelectorExtension\Extension:
    selectorFilePath: dictionary.yml
    timeout: 10
    contexts:
    UIBusinessSelector: ~

    But I get:

    [Behat\Testwork\ServiceContainer\Exception\ExtensionInitializationException] `OrangeDigital\BusinessSelectorExtension\Extension` extension file or class could not be located.

    Behat v3.0.15

    What am i doing wrong?

  • 2014-12-04 weaverryan

    Hey Sai!

    So you're using something like a custom jQuery date-picker? The solution depends. First, you'll of course need a custom step for this, e.g.:


    And I fill in the "Birthday" date picker with "20/12/1985"

    For the implementation, you have 2 choices. First, you'll find the correct field based on the label - something like this (assuming $fieldLabel is the value passed to your function for "Birthday"):


    $field = $this->getSession()->getPage()->findField($fieldLabel);

    Then, you have 2 choices:

    1) Use a bunch of CSS to find different physical elements of your calendar and click those. In other words, do exactly what the user does - click some icon, then click to change the month, etc).

    2) Use JavaScript directly. Most of the time, a date-picker has some JS API you can use to set the date. I'm inventing this API, but for example:


    $this->getSession()->executeJavaScript(sprintf(
    '$("#%s").datepicker("set", "%s");',
    $field->attr('id'),
    $dateString
    );

    I hope that helps!

  • 2014-12-02 Sai Satish

    I'm trying to select the date from datepicker/calendar for Date of Birth field. However, unable to do it. Can anyone suggest me with the possible working code for "selecting a required date from the calendar for DOB field.

  • 2014-08-04 codedungeon

    It's all good! Since posting the comment, I have since figured everything out and have a good grasp on the changes between v2 and v3. As you stated, mostly just configuration items.
    As we discussed on twitter, I am working on a conversion guide between v2 and v3 so was looking for any information on v3 that I could find. As with most programming tasks, it required a lot of trial and error but all is good now!
    - mse

  • 2014-08-04 weaverryan

    You're right :). We haven't started on it yet, but we definitely will soon. The good news is that it's not too much different. The installation and configuration are the biggest changes, but the underlying usage is all pretty much the same :). In the mean-time, I do have a video presentation on using Behat v3 if you're curious :) https://www.youtube.com/wat....

    Thanks!

  • 2014-08-03 codedungeon

    So, it seems that Behat3 is more than stable at this point! Have you done any work towards upgrading your course to use Behat3

  • 2014-07-22 weaverryan

    Hey Michael!

    Wow, that's really interesting. It's not totally uncommon for things to work differently between JavaScript and non-JavaScript, because there are subtle differences - e.g. if a button is "hidden" with CSS in JavaScript, Selenium (correctly) won't find it, but Goutte will. But I *am* surprised that you've found something that works in Sahi, but not in Selenium. I use Selenium for everything and find it very dependable, but obviously you've found something here that's definitely wonky :). I wouldn't necessarily give up on Selenium, but Sahi is also very good (though it doesn't execute quite as quickly in my experience).

    Thanks for the comment!

  • 2014-07-21 Michael

    The Velociraptor example with Selenium2 works, but when I search "OHM (band)" for "David Eagle" (copied from the page source), it fails. If I match on another band member, "Chris Poland", it works. The match on "David Eagle" works in Goutte ("@javascript" commented out). I'm running selenium-server-standalone-2.42.2.jar. I verified that selenium-server-standalone-2.39.0.jar is also defective. I installed sahi and it works so I will not be using Selenium again.

  • 2014-04-24 weaverryan

    Hi there!

    For the most part, yes. The vast majority of things are not changing: the scenarios, philosophy, mapping to functions, Mink, etc. There will be some changes - setup/configuration, subcontexts and chained steps - but these are small pieces of the full Behat picture :). We'll also upgrade the tutorial once Behat 3 is stable, and you can come back then to see those updates :).

    I hope that helps!

  • 2014-04-21 codedungeon

    Will these procedures still work with Behat 3, despite their recent changes? Looking for a few good Behat tutorials but want to make sure they work with Behat 3

  • 2014-02-06 weaverryan

    Hi Anamika!

    I'm not sure what the issue is :). I would:

    1) Find the #large field via Mink and set the file on it (using the method we talked about earlier).

    2) I would trigger the upload however the user does - click a button, etc. I'm not sure about this part, because while I see a button that will open the file upload "Browse" box, I don't see any button or JavaScript that would then submit the form or start the upload. But basically, the issue is not how to browse and select the right file - that should be taken care of with (1) - it's about taking whatever user action after this to actually submit the form or start the file upload. For this part, just do whatever the user does - that will take care of you 99% of the time.

    Cheers!

  • 2014-02-06 Anamika

    Yeah sorry had to stop this work and moved to another, back this again!!! Ya you are right, i tested file upload process it works fine with behat/mink (I attach the file..), makes ajax call etc. But found that issue is different, here following is the structure of file upload in my application. There you can see actual file filed is invisible where as browse button invoke the file filed event. In which case test scenario (I attach the file) is failing. Through javascript also can't write to file field where browser doesn't allow for security reason.

    <input type="file" style="display:none" placeholder="Filename ..." id="large" name="largeUploadImage" class="form-control fileUpload">
    <input type="text" placeholder="Filename ..." id="largeImgFile" class="form-control">

    <button onclick="$('input[id=large]').click();" type="button" class="btn btn-primary">Browse</button>

    Hope you got the issue! Thank you in advance :)

  • 2014-01-24 weaverryan

    It sounds like this is your situation: when the user selects a file, then some JavaScript causes an AJAX POST request to be made in the background. Is that accurate?

    If so, first, obviously make sure you're running the tests in Selenium so that JavaScript fires. I'm sure you're already doing this, but I wanted to mention it! Second, if you're JavaScript is written to fire on the "change" event of the file upload, then I would *think* that attaching the file via Mink would cause this event to trigger (and so your JavaScript would run). I've never tried that with a file upload field, so I can't be sure - but generally-speaking, if you click something or fill out some form field with Behat, that is really happening in a real browser, so it triggers all the same JavaScript events as normal. If this is *not* the case for the file upload box, then yes, I would work around it by manually executing JavaScript that triggers the "change" event on the file upload field. That's no ideal, but if setting the file isn't triggering the event, then you'll need to.

    I hope that helps!

  • 2014-01-24 Anamika

    Hey Weaverryan,
    Thank you it works!! Now strucked up with another query, in my application once the file (image file) is selected makes an API call (post method) which takes care of storing file into respective folder. But API call is not happening through test scenarios, so trying to invoke the API call using executeScript. But it doesn't working out for me. So how can i solve it now? wanted your thoughts and suggestions on this. Waiting!!!!!!!!!!!!!!!!!!!

  • 2014-01-22 weaverryan

    Hi Anamika!

    Yes, you're using the correct statement! Behind the scenes, when you say "I attach the file 'filepath' to 'field'", the "field" is found by its label name (like always) and then this method is called on that element: http://mink.behat.org/api/b...

    When you use that method directly, you give it the absolute file path to the file on your system that you want to upload. Of course, including a full-path in a scenario is not great - we want to keep those ugly details hidden. So when you use this inside Behat, you should say something like:

    I attach the file "foo.pdf" to "Upload file"

    Behat will look in a specific directory for "foo.pdf" - this directory is defined in your behat.yml file under the "files_path" key: http://extensions.behat.org.... So in your behat.yml, under the MinkExtension configuration (so right next to selenium2: ~, goutte: - see example here: http://knpuniversity.com/sc... - add a `files_path` key, and point that to some directory. Then, put your `foo.pdf` in that directory.

    I hope that helps out :). Whenever your not totally sure how something is working, it's a good idea to look in the MinkExtension class and see what the code there is doing: https://github.com/Behat/Mi...

    Good luck!

  • 2014-01-22 weaverryan

    Hey Thomas

    I'm sorry you were disappointed with the missing Symfony2 pieces :/. I'm going to look into that and see if the description needs to be updated - that may have been my bad :).

    Installing PHPUnit is historically a pain because it was done via Pear (which is a pain). However, 2 things:

    1) You don't need PHPUnit - it's just an extra thing that give you the assert_equals, etc functions - we talk about that briefly here: If you *aren't* using PHPUnit, then you can just do the checks yourself. For example:

    assertEquals($a, $b, 'These are not equal!')

    Would become

    if ($a != $b) {
    throw new \Exception('These are not equal');
    }

    2) The best way to install PHPUnit (and now the recommended way) is via Composer: http://phpunit.de/manual/cu.... If you do this, PHPUnit (and those files) are in your vendor directory. The require statements in this case should look like:


    require_once __DIR__.'/../../vendor/phpunit/phpunit/PHPUnit/Autoload.php';
    require_once __DIR__.'/../../vendor/phpunit/phpunit/PHPUnit/Framework/Assert/Functions.php';

    The other require statements that Behat adds by default only work if (a) you have PHPUnit installed via Pear and B) Have all your PHP-Pear include path setup (which isn't always easy).

    I hope that helps out! About Symfony2 - the key is the Symfony2Extension: http://extensions.behat.org.... What it gives you (most importantly) is access to Symfony's Container from within your FeatureContext class. Here's how that would look once you have that extension installed: https://gist.github.com/wea....

    I'll open an issue about adding some of these notes (e.g. Symfony2 integration, more info on PHPUnit) - I think you have good questions, so the notes will almost definitely be useful for others. Issue: https://github.com/knpunive...

    Thanks!

  • 2014-01-22 Anamika

    Hi there, I suppose to write scenario for image upload, i used behat "I attach the file 'filepath' to 'field'" but it doesn't work. Please help me.

  • 2014-01-22 Thomas

    I am a little disappointed with this screencast. It did teach a lot about behat and mink and I learned a lot. But this page https://knpuniversity.com/s... in the description it says if I am using Symfony2 there'll be special tips to get me rolling. There were none. Instead, the framework used was Silex, which is based on Symfony2, I understand, but I was expecting information directly with Symfony2.

    I am also having a hell of a time getting PHPUnit to work with Behat. I commented out the require_once lines and then the tests don't run at all. I have PHPUnit installed and even gave the absolute path starting with the drive letter on my windows box and it doesn't seem to work at all. It just displays the Scenario line of the feature and doesn't move on. It doesn't even say that so many steps were run or anything.

  • 2014-01-22 Thomas

    For anyone else using windows. behat-ls feature won't work for us. I created an issue on github and hopefully we can figure it out. :) https://github.com/knpunive...

    I did find out the command in windows that works like rm -r try:
    `system('rd /S /Q '.realpath('test'));`

    It worked well for me.

  • 2014-01-21 weaverryan

    Hi theMan

    No worries :). The PDF download is simply a written version of what the spoken audio is in the video. So both are the same. But, I'm not sure if that's what you're talking about exactly. So that we can get you going, can you email me - ryan[at]knplabs.com?

    Thanks!

  • 2014-01-21 theMan

    Thank's for that Ryan. I'm kinda concerned if I might be asking too much questions. I'm not from a developer background, but I've also bought the PHP to help with the B§8§§ehat course. But right now I'm struggling with the method functions that helps identify Xpath of fields to edit, and click. I've tried the video and the PDF files but it seems like plenty of alternatives were tried and it looks distracting.

    Can you please identify the best path to follow from the video and the pfd, e.g. page no and stage in video.

    Thanks

  • 2014-01-21 weaverryan

    Hi Femi Fet!

    It's just *1* dash - "php bin/behat -dl". But that's my fault - I had a typo with two dashes in the intro chapter. I've added a quick issue, which I'll fix and deploy today: https://github.com/knpunive...

    Thanks for asking the question!

  • 2014-01-21 weaverryan

    Ah, my mistake! I'll answer it right now!

  • 2014-01-18 theMan

    When I try to run, php bin/behat --dl, I get the error below:

    [RuntimeException]

    The "--dl" option does not exist.

    behat [--init] [-f|--format="..."] [--out="..."] [--lang="..."] [--[no-]ansi] [--[no-]time] [--[no-]paths] [--[no-]snippets] [--[no-]snippets-paths] [--[no-]multiline] [--[no-]expand] [--story-syntax] [-d|--definitions="..."] [--name="..."] [--tags="..."] [--cache="..."] [--strict] [--dry-run] [--rerun="..."] [--append-snippets] [features]

  • 2014-01-18 theMan

    You deleted the wrong question, and that was a legitimate one with the --dl query.

  • 2013-12-29 weaverryan

    Hi there!

    Hmm. If you're not running the Selenium server in the background, that would certainly cause the browser to not load. BUT, you'll also receive a huge error :).

    If it *is* running and you're in Behat, make sure you have the `@javascript` above your scenario. If you're using Mink directly, make sure you're using the `Selenium2Driver`, not the `GoutteDriver` - one of these two is probably the cause if you don't see a big error.

    Good luck!

  • 2013-12-29 Guest

    Hi, everything worked, but the browser didn't load up. What am I missing here?

  • 2013-12-17 weaverryan

    Hey Maksim!

    That's very interesting! I haven't benchmarked this, but there could be 2 reasons:

    1) Obviously, you skip the parsing of the English. This will take some time, but I'm not sure how much. It wouldn't seem like too much, but it could be.

    2) The built-in code uses a big (but awesome) xpath statement internally to find the fields based on their label or a bunch of other things. Your xpath uses only the id, which is quite fast.

    I'd be careful to not do too much of this, because you'll not have as much code-reuse and the xpaths used here aren't as flexible as the ones used internally. Plus, you're probably going to lose most of your time opening up a browser if your tests use JavaScript.

    That being said, since logging in is really common, making a tweak like this could save time. I'd probably do it the easy way first, then modify things later if you want to. But regardless, this is an interesting comment!

    Thanks!

  • 2013-12-12 Maksim Borissov

    Apparently, doing iAmLoggedIn functionality with:

    $page = $this->getMink()->getSession()->getPage();

    $username = $page->find('xpath', '//input[@id="username"]');
    $username->setValue('Ryan');

    $password = $page->find('xpath', '//input[@id="password"]');
    $password->setValue('foobar');

    $loginButton = $page->find('xpath', '//button[@id="login"]');
    $loginButton->press();

    would be much faster than

    return array(
    new Given('I am on "login"'),
    new Given('I fill in "Username" with "Ryan"'),
    new Given('I fill in "Password" with "foobar"'),
    new Given('I press "Login"'),
    );

    It looks a bit more uglier and needs some knowledge about manipulating DOM but on my setup, with my own tests, I get 10-20 less execution time.

    I'm using Behat/Mink + Sahi Driver

  • 2013-10-25 weaverryan

    Hi Vishal!

    I don't think it's a bug - it's just that if you find something in the zero position, it returns 0, which == false. So you're right that the original code in the text never worked :) - the code in the actual video (and now in the code download) uses === false and works nicely now.

    Cheers!

  • 2013-10-25 Vishal Khialani

    array_search() seems to have a bug in it for any value which is in key '0' I am not sure how yours worked. ref :http://php.net/manual/en/fu...

  • 2013-09-23 weaverryan

    Hi Felipe!

    Ah, thanks for the kind words and taking the time with the notes here :).

    1. I have never seen this before, but you're right! In Firefox, changing the font size makes the video player act out. Not cool - I've added this as a bug in our tracker.

    2. I agree - it would be helpful to leverage the different sections (which already exist) to organize things even better. If I understand you correctly, you're proposing showing a 1-2 second "slide" in the middle of the video as you move from section to section. Is that right? I'd also like to mark the different sections on the video or have an in-video TOC that's clickable - it's something we have on our minds :).

    Any other thoughts are always warmly appreciated.

    Thanks again!