The example will visit Wikipedia’s homepage and interact with the autocomplete feature of the search bar.
First, create a folder to contain the project’s files and install the needed packages:
composer require --dev behat/behat behat/mink-extension behat/mink-goutte-driver dmore/behat-chrome-extension
Now, initialize Behat and create a configuration file.
touch behat.yml # creates empty configuration file
The content of the configuration file should be as follows:
Writing a simple Behat test
After running the `behat --init` command before, there should be a `features` folder where test files can be placed. Inside that folder, create a file called search.feature.
The file should contain the following:
In order to find articles to read
As a site user
I need to be able to use the search bar
Scenario: Search for a term
Given I am on the homepage
When I fill in "search" with "pantheon"
And I press "searchButton"
Then I should see "Pantheon (software), a web development platform"
And I should see "Pantheon (desktop environment), a GTK+-based desktop environment"
The test will visit Wikipedia’s homepage as defined in the `base_url` setting for the MinkExtension in `behat.yml`. Then, it will enter the term `pantheon` in the search bar at the top right of the page and click the search button. Finally, it will check if the next page contains texts that would be part of the search results.
To run the tests, execute the behat command with no parameters.
The tests should pass and a summary like the following should be printed at the end:
1 scenario (1 passed)
5 steps (5 passed)
A glimpse at Behat, Mink, MinkExtension, and GoutteDriver
Let’s step back a bit and analyze what we have done so far and what role each of the packages play. Behat will parse the `search.feature` file looking for scenarios that contain our test cases. Each scenario is a collection of steps that represent the actions a user would take while interacting with the website. Steps are written in Gherkin, a human readable language, and start with keywords like `Given`, `When`, `Then`, `And`, and `But`. These steps are matched by Behat to step definitions which are PHP functions with instructions to interact with the website. For example, the step `Given I am on the homepage` is match to the following step definition:
public function iAmOnHomepage()
For every step used in a scenario, Behat will look for a matching step definition which is a custom PHP function with specific PHP annotations. If no matching function is found, you will get an error indicating that there are undefined steps. In this example, we did not write any PHP code; how is it working?
The steps used in the example are provided by the MinkExtension via the MinkContext. This context was added to the project as indicated in the `behat.yml`. It comes with many steps and step definitions for common tasks like visiting urls, clicking links, pressing buttons, filling out form elements, and asserting expected text appears on the site. These, and others, are actions that a user would do via the browser while interacting with a website. Does that mean that we are using a real browser under the hood to run the tests? Sometimes.
Many types of browsers, such as Firefox and Chrome
Multiple browsers at the same time to execute tests in parallel
Remote browsers, such as inside a virtual machine or a totally different computer
This flexibility comes with some overhead. The biggest one is that you need Selenium Standalone Server, which itself requires Java. Adding another language to your stack might not be something you could do in every project. A lighter alternative is to use the Chrome driver, which lets you control Google Chrome either in headless mode or showing the user interface. We are also going to use the Behat Chrome Extension.
Scenario: Search for a term
Scenario: Search for a term using autocomplete
Given I am on the homepage
When I select the first autocomplete option for "behat computer" on the "search" field
And I press the search button
Then first header of the page should be "Behat (computer science)"
And I should see "Behat is a test framework for behavior-driven development written in the PHP programming language."
// Based on code by Lyle Mantooth.
// @see https://gist.github.com/IslandUsurper/12723643dddc9315ff71
$this->getSession()->wait(1000, 'jQuery(".suggestions").is(":visible") === true');
$xpath = $element->getXpath();
// Down key.
You also need to understand how the site works in order to adequately write step definitions. Wikipedia has a `div` tag with a `suggestion` class that becomes visible when the search autocomplete is triggered. We are using that to wait for the autocomplete to appear and then press the down key. In this case, we are triggering separate `keyDown` and `keyUp` because this is the expectation from the site. By instructing the down key should be pressed, the first element of the autocomplete is selected and the text is copied to the search bar.
The behat.yml configuration will be slightly different depending on which driver you want to use. The example below is for the ChromeDriver:
Start Chrome in Debugging mode
The last thing to do before runnig the tests is to start Chrome or Chromium in debugging mode. The exact command to run will depend on your operating system and whether you are using Chrome or Chromium. In any case, you need to find the browser binary and, from the command line, execute it passing some flags. The examples below assume a `google-chrome` binary available in your PATH environment variable. For possible locations of the browser executable, have a look at this reference.
If you want to run the browser in headless mode, execute:
google-chrome --disable-gpu --headless --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222
If you want to show the browser’s interface, execute:
google-chrome --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222
In both cases, you should see a message like this:
DevTools listening on ws://0.0.0.0:9222/devtools/browser/[uuid]
Note that if you decide to run Chrome showing the browser’s interface, you might have to close any open browser window before running the command or you might get an error like this:
Could not fetch version information from http://127.0.0.1:9222/json/version. Please check if Chrome is running. Please see docs/troubleshooting.md if Chrome crashed unexpected. (RuntimeException)
Finally, execute the `behat` command with no parameters:
You can find the code for this demo in this repository.