Introduction
My colleague Damien Gilbrin has a lot of experience about Behat. He just partecipate to a MeetUp where he explained how to properly use Behat also integrating Selenium and BrowserStack.
Here the presentation in french language:
- Behat : https://www.damiengilbrin.fr/behat
- BrowserStack : https://www.damiengilbrin.fr/browserstack
Now i will show you the practical example that Damien publish on github
Stack
- Docker
- Symfony 4
- Behat
- Selenium
- BroswerStack
Installation
- You must have Docker installed
- Retrieve the sources repository (git clone)
- Copy the .env.dist file to .env (and modify it if you use BrowserStack)
- Launch the Docker container via the docker-compose up command
- Install the vendors:
- Run the command docker exec -it behatmeetupzendfr_php_1 bash to connect to the PHP container
- Execute this command to install the vendors: composer install
Once the containers are running, go to the address: http://localhost:8080
Important files
The example is a simple cart, where you can add a product, remove it or see the list of products included in your cart. The entry point is the DefaultController:
- src/Controller/DefaultController.php
A service takes care of performing operations in memory:
- src/Service/CartServiceSession.php
The scenarios of Behat are here:
- tests/Behaviour/Features
The Context are here:
- tests/Behaviour/Bootstrap/Context
A quick tour inside code
In this article I do not want to present Behat, for this I highly recommend reading the documentation. It is however interesting to see how easily you can test your application.
For this reason we are going to write our first Behat scenario:
//tests/Behaviour/Features/Interface/Cart.feature
@cart @javascript
Feature: Cart interface Test
@cart-add-1
Scenario: Add 1 product to cart
Given I am on home page
When I add "Article A" to my cart
And I see my cart
Then the cart contain 1 "Article A" product
And I have 1 article on cart
And the total amount is 10.00 Euro
Each sentence of the scenario is linked (by annotations) to a method defined in the context. So the sentence I am on home page, it’s translated by the method iAmOnHomePage of tests/Behaviour/Bootstrap/Context/CartContext.php.
/**
* @Given /^I am on home page$/
*/
public function iAmOnHomePage()
{
$this->visit('/');
}
and in the same way the sentence I add « Article A » to my cart it’s translated by the method iAddToMyCart
/**
* @When /^I add (\d+ )?"([^"]*)" to my cart$/
* @param string $productName
* @throws Exception
*/
public function iAddToMyCart(string $quantity, string $productName)
{
//Use default session, you can update to add "MyBrowserStackChrome" for specific test on navigator
$session = $this->getMink()->getSession();
//Find all article
$articleElementList = $session->getPage()->findAll('css', '.article');
foreach ($articleElementList as $articleElement) {
//Is the expected article ?
/** @var $articleElement ElementInterface */
if ($articleElement->find('css', '.title')->getText() != $productName) {
continue;
}
//Iterate for count click (add 1 time, 2...)
$countIterate = trim($quantity) === '' ? 1 : (int) trim($quantity);
for ($count = 0; $count < $countIterate; $count ++ ) {
//Click on button
$button = $articleElement->find('css', 'button');
$button->click();
//Wait button is not disabled (ajax request)
$session->wait(
20000,
sprintf(
'!document.getElementById(\'%s\').disabled',
$button->getAttribute('id')
)
);
}
//It's ok !
return;
}
//Article not found
throw new \Exception(sprintf('Article %s not found', $productName));
}
You can also use PHPUnit asserts. This is just an example to show how it works.
It should be noted that Behat by default uses Mink. Mink is a browser emulator abstraction layer. It hides emulator differences behind a single, consistent API. So you can use Mink + Selenium to follow in real time yours tests step by step.
For this reason the project use Docker Selenium, so in docker-compose.yml we will have:
chrome:
image: elgalu/selenium
depends_on:
- hub
volumes:
- /dev/shm:/dev/shm
privileged: true
environment:
- NOVNC=true
- SELENIUM_HUB_HOST=hub
- SELENIUM_HUB_PORT=4444
- SELENIUM_NODE_HOST={{CONTAINER_IP}}
- SCREEN_WIDTH=1300
- SCREEN_HEIGHT=999
- VIDEO=false
- GRID=false
- CHROME=true
- FIREFOX=false
Launch Behat tests
Now you can run tests:
php vendor/bin/behat -vvv --no-interaction --tags=XXXXX
You can add –tags = TagName with the name of the tag using « @ » symbol in the Feature file.
And with Selenium it is possible to see in real time the execution of the script at this address: http://127.0.0.1:6081
Browser Stack
The last piece of the puzzle is BrowserStack. If you don’t want use Selenium you can use BrowserStack.
BrowserStack is a cloud web and mobile testing platform that enables developers to test their websites and mobile applications across on-demand browsers, operating systems and real mobile devices, without requiring users to install or maintain an internal lab of virtual machines, devices or emulators.
So if you want use it in the project you can add to docker-compose.yml
browserstacklocal:
build:
context: ./docker/browserstacklocal
env_file:
- .env
depends_on:
- nginx
And you must update the Dockerfile:
FROM debian:stable-slim
ENV BROWSERSTACK_LOCAL_KEY=
COPY ./entrypoint.sh /
RUN ["chmod", "+x", "/entrypoint.sh"]
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y wget unzip
RUN wget https://www.browserstack.com/browserstack-local/BrowserStackLocal-linux-x64.zip && \
unzip BrowserStackLocal-linux-x64.zip && \
rm BrowserStackLocal-linux-x64.zip && \
chmod +x BrowserStackLocal && \
mv BrowserStackLocal /usr/local/bin
ENTRYPOINT ["/entrypoint.sh"]
And in .env you must add yours BrowserStack credentials.
Conclusions
The advantages of using Behat are manifold and are well explained in this article. And it’s very easy to implement using Docker and Symfony.
So using Behat + Selenium or Behat + BrowserStack you will have a top test environment.
Enjoy!
References
- https://github.com/DamienGilbrin/BehatMeetup
- https://blog.rafalmuszynski.pl/how-to-configure-behat-with-symfony-4 (image post)
- https://www.damiengilbrin.fr/behat
- https://www.damiengilbrin.fr/browserstack
- http://behat.org/en/v2.5/
- http://mink.behat.org/en/latest/index.html
- http://www.codepositive.com/articles/benefits-behat
- https://github.com/elgalu/docker-selenium
- https://en.wikipedia.org/wiki/BrowserStack
Thanks for the write up!
Some remarks:
– I’m not sure what to do with the .env file. What to remote / replace with.
– sudo docker exec -it behatmeetup_php_1 bash
– it should be port : http://127.0.0.1:6080 (not 6081) which is used in docker-composer.yml
– it was initially not clear to run behat in the PHP container (doh). For me it was better to have the ‘Launch Behat tests’ section right after the installation.
Hi, looks like you took the photo from https://blog.rafalmuszynski.pl/how-to-configure-behat-with-symfony-4/ without asking anyone. I hope you will remove it or add credits.
Rafal, photo owner.
Sorry Rafal, i added the credits at the end of post.