Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine


Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

We've created our features, which is really nice because we can see the business value of each and decide which one to start on first. I want to start with our product admin feature, so our admin users can start loading in data.

Now that we've selected that, we'll start adding scenarios to the feature which are essentially user stories. My first scenario is going to say, "when I go to the admin area and click on products, I see the products listed."

So let's start with:

... lines 1 - 5
Scenario: List available products
... lines 7 - 20

Do keep in mind that this line doesn't matter too much, no need to be Shakespeare.

Given, When and Then

For these scenarios I need you to think as if you are the admin user. We'll talk in the first person point of view at the intended user's technical level. Meaning, clicking on buttons an admin user can actually recognize and viewing things that they will see. Put yourself in their shoes.

Given: Setup

Scenarios always have three parts, the first is Given where you can create any type of setup before the user story starts. So in our case, if we want to list products, we need to make there are some in the database to see:

... lines 1 - 6
Given there are 5 products
... lines 8 - 20

Why am I saying exactly "there are 5 products"? Great question, the exact phrasing here doesn't matter at all. I'm just using whatever language sounds most clear to me. Move on down to the next line:

... lines 1 - 7
And I am on "/admin"
... lines 9 - 20

Using the word And here extends the Given line to include more setup details. With these two lines, we'll have 5 products in the database and start the test on the /admin page.

When: User Action

The second part of every scenario is When which is the user action. Here, "I" - the admin user - actually take action. In our case, the only action is clicking products:

... lines 1 - 8
When I click "Products"
... lines 10 - 20

This is good because that's the name of the link and it reads very clearly.

User Expectations

Finally, the last part of every scenario is Then, this is where we witness things as the user. In our scenario, we should see the 5 products that we set up in our Given:

... lines 1 - 9
Then I should see 5 products
... lines 11 - 20

Always use language that is clear to you after your Given, When, Then or And in your scenarios.

Only play God in Given

In Given you can add things to the database before hand, but once you are in When and Then you should only be taking actions that the admin user could take and viewing things they can view. This means we won't be using CSS selectors in our scenarios or phrasing such as "Then a product should be entered into the database" because a user can't see that happen. However, the user could see a helpful message, like "Celebrate, your product was saved!"

BDD with a New Scenario

Let's create a new scenario for functionality that doesn't actually exist yet: adding a new product. Time to plan out this scenario!

... lines 1 - 11
Scenario: Add a new product
... lines 13 - 20

We don't need to add any products in the database before hand so we just start with:

... lines 1 - 12
Given I am on "/admin/products"
... lines 14 - 20

We're going to want a button on this page that says "New Product". So let's add clicking that to the process of creating a new product:

... lines 1 - 13
When I click "New Product"
... lines 15 - 20

Clicking this will take us to another page with a form containing fields for name, price and description. To keep our When going to include the action of filling out this form we'll use And:

... lines 1 - 14
And I fill in "Name" with "Veloci-chew toy"
And I fill in "Price" with "20"
And I fill in "Description" with "Have your velociraptor chew on this instead!"
... lines 18 - 20

There is a secret reason of why I'm using language like "I fill in" after the And, which we'll cover soon. Lastly, in our process I'll expect to hit a save button to finish creating my new product. So let's add another line to our scenario:

... lines 1 - 17
And I press "Save"
... lines 19 - 20

At this point my product should be saved and I will be redirected to another page with a success message to prove that this worked. This is where we'll say:

... lines 1 - 18
Then I should see "Product created FTW!"

Isn't that a nice way to plan out your user flow? When we do finally code this, we'll know exactly how everything should work.

Leave a comment!

Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial uses a very old version of Symfony. The fundamentals of Behat are still valid, but integration with Symfony will be different.

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": ">=5.4.0, <7.3.0",
        "symfony/symfony": "^2.7", // v2.7.4
        "twig/twig": "^1.22", // v1.22.1
        "sensio/framework-extra-bundle": "^3.0", // v3.0.16
        "doctrine/doctrine-bundle": "^1.5", // v1.5.1
        "doctrine/orm": "^2.5", // v2.5.1
        "doctrine/doctrine-fixtures-bundle": "^2.2", // v2.2.1
        "behat/symfony2-extension": "^2.0" // v2.0.0
    "require-dev": {
        "behat/mink-extension": "^2.0", // v2.0.1
        "behat/mink-goutte-driver": "^1.1", // v1.1.0
        "behat/mink-selenium2-driver": "^1.2", // v1.2.0
        "phpunit/phpunit": "^4.8" // 4.8.18