Symfony/BDD example 02: red, green, blue

30 December 2014

This is the second example in Symfony/BDD series. It demonstrates how to create simple web pages.

1. Background

I assume that you have already read the first part: Symfony/BDD example: Hello, world!

The task at hand can be specified as follows:

2. Introductory step

2.1. Start the project

Create a new directory and clone my Symfony Standard repository:

# Host OS
$ mkdir symfony-bdd-example-02-red-green-blue
$ cd symfony-bdd-example-02-red-green-blue
$ git clone git@github.com:by-examples/symfony-standard.git .

2.2. Create a starting point for the project

Create a new orphan branch that starts at the tag Symfony Standard v2.6.1:

# Host OS
$ git checkout --orphan 2.6.1/bdd-example-02-red-green-blue v2.6.1

Commit your change:

# Host OS
$ git add -A
$ git commit -m "Symfony Standard 2.6.1"

2.3. Customize the project

To avoid repeating the same actions again and again every time I start a new project, I use branches.

To introduce all this changes in your project, you can cherry-pick them:

# Host OS
$ git cherry-pick origin/2.6.1/Gitignore
$ git cherry-pick origin/2.6.1/Cleanup
$ git cherry-pick origin/2.6.1/Vagrant
$ git cherry-pick origin/2.6.1/Speedup
$ git cherry-pick origin/2.6.1/Behat
$ git cherry-pick origin/2.6.1/BehatInitialization

2.4. Install the dependencies

Boot the VM with:

# Host OS
$ vagrant up
$ vagrant ssh

and run:

# Guest OS
$ composer install -o

When this is done, commit you changes with:

# Host OS
$ git add -A
$ git commit -m "Updated dependencies"

3. Run Behat - project is GREEN

Now, try to run:

# Guest OS
$ bin/behat

You will get the output similar to:

No scenarios
No steps
0m0.03s (9.00Mb)

The project is GREEN.

GREEN

4. Tests - project is RED

Create the file features/pages.feature with the following contents:

Feature: I want to see three web pages and main menu

  Scenario: Red page
    Given I am on homepage
     Then I should see "Red, red, red"
      And I should see "Main menu"

  Scenario: Green page
    Given I am on "/green.html"
     Then I should see "Green, green, green"
      And I should see "Main menu"

  Scenario: Blue page
    Given I am on "/blue.html"
     Then I should see "Blue, blue, blue"
      And I should see "Main menu"

Run Behat:

# Guest OS
$ bin/behat

The project is RED.

RED

Commit the test:

# Host OS
$ git add -A
$ git commit -m "[BDD:RED] tests for three pages: red, green, blue"

5. Create three pages and menu - project is GREEN

This task consist of:

5.1. Create actions

Change the contents of the file src/AppBundle/Controller/DefaultController.php as follows:

//Filename src/AppBundle/Controller/DefaultController.php
...
class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function redAction()
    {
        return $this->render('default/red.html.twig');
    }

    /**
     * @Route("/green.html", name="green")
     */
    public function greenAction()
    {
        return $this->render('default/green.html.twig');
    }

    /**
     * @Route("/blue.html", name="blue")
     */
    public function blueAction()
    {
        return $this->render('default/blue.html.twig');
    }

}

5.2. Create views

Create three files.

The first file app/Resources/views/default/red.html.twig:

//Filename: app/Resources/views/default/red.html.twig
{% extends '::base.html.twig' %}

{% block body %}
    <p>Red, red, red</p>
{% endblock body %}

The second file app/Resources/views/default/green.html.twig:

//Filename: app/Resources/views/default/green.html.twig
{% extends '::base.html.twig' %}

{% block body %}
    <p>Green, green, green</p>
{% endblock body %}

The third file app/Resources/views/default/blue.html.twig:

//Filename: app/Resources/views/default/blue.html.twig
{% extends '::base.html.twig' %}

{% block body %}
    <p>Blue, blue, blue</p>
{% endblock body %}

5.3. Create main menu

Change the contents of the app/Resources/views/base.html.twig by adding the main menu:

//Filename: app/Resources/views/base.html.twig
...
<body>
    <div>
        <h4>Main menu</h4>
        <ul>
            <li><a href="{{ path('homepage') }}">Red</a></li>
            <li><a href="{{ path('green') }}">Green</a></li>
            <li><a href="{{ path('blue') }}">Blue</a></li>
        </ul>
    </div>
    {% block body %}{% endblock %}
    {% block javascripts %}{% endblock %}
</body>
...

5.4. Cleaning

Remove the file app/Resources/views/default/index.html.twig.

# Host OS
$ rm app/Resources/views/default/index.html.twig

6. Run the tests

Clear the cache:

# Guest OS
$ php app/console cache:clear --env=prod

and run the tests:

# Guest OS
$ bin/behat

The project is GREEN.

GREEN

Commit your changes with:

# Host OS
$ git add -A
$ git commit -m "[BDD:GREEN] code for tests: red, green, blue"

7. Visit app with your browser

Run web browser and visit:

http://localhost:8880/
http://localhost:8880/app_dev.php/

You can also view your application in guest using lynx:

# Guest OS
$ lynx http://localhost/
$ lynx http://localhost/app_dev.php/

8. Test the efficiency

You can test the efficiency of the application with:

# Guest OS
$ ab -n 100 http://localhost/green.html

Here are the results I get on my OS X machine (i7/8MB RAM/ssd):

Concurrency Level:      1
Time taken for tests:   1.628 seconds
Complete requests:      100
Failed requests:        0
Non-2xx responses:      100
Total transferred:      17000 bytes
HTML transferred:       0 bytes
Requests per second:    61.42 [#/sec] (mean)
Time per request:       16.282 [ms] (mean)
Time per request:       16.282 [ms] (mean, across all concurrent requests)
Transfer rate:          10.20 [Kbytes/sec] received

My results from Windows machine (i5/4MB RAM/not ssd):

Server Software:        Apache/2.4.10
Server Hostname:        localhost
Server Port:            80

Document Path:          /green.html
Document Length:        517 bytes

Concurrency Level:      1
Time taken for tests:   4.525 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      78000 bytes
HTML transferred:       51700 bytes
Requests per second:    22.10 [#/sec] (mean)
Time per request:       45.251 [ms] (mean)
Time per request:       45.251 [ms] (mean, across all concurrent requests)
Transfer rate:          16.83 [Kbytes/sec] received	

8. Remove unnecessary commits

The history of your project is now linear and contains 10 commits. The command:

$ git log --oneline

prints the output similar to:

bb07e3c [BDD:GREEN] code for tests: red, green, blue
8086044 [BDD:RED] tests for three pages: red, green, blue
9b35a3a Updated dependencies
c3466fb [STARTUP] Behat initialization
716bea7 [STARTUP] Behat installation
2030974 [STARTUP] Vendor, cache and log in /tmp/symfony2app/
c957651 [STARTUP] Vagrant
f523da2 [STARTUP] Remove unnecessary files
cc41c00 [STARTUP] Gitignore and gitattributes
41d5d5c Symfony Standard 2.6.1

If you use --all switch for $ git log, you will see a lot of other commits (the original commits from Symfony Standard). To remove them, use the following commands:

$ git remote rm origin
$ git branch -D 2.7
$ git tag | xargs git tag -d
$ git reflog expire --all --expire=now
$ git prune
$ git gc

Now your repository contains only 10 commits listed above.

9. The Example

You will find the source code of the example on GitHub.

For the instruction how to run the example refer to README.md file.

Fork me on GitHub